Merge llvm-project main llvmorg-14-init-11187-g222442ec2d71

This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-14-init-11187-g222442ec2d71.

PR:		261742
MFC after:	2 weeks
This commit is contained in:
Dimitry Andric 2021-12-02 22:49:08 +01:00
commit 4824e7fd18
751 changed files with 23675 additions and 13614 deletions

View File

@ -41,6 +41,7 @@ clang/lib/AST/CMakeLists.txt
clang/lib/ASTMatchers/CMakeLists.txt clang/lib/ASTMatchers/CMakeLists.txt
clang/lib/ASTMatchers/Dynamic/CMakeLists.txt clang/lib/ASTMatchers/Dynamic/CMakeLists.txt
clang/lib/Analysis/CMakeLists.txt clang/lib/Analysis/CMakeLists.txt
clang/lib/Analysis/FlowSensitive/CMakeLists.txt
clang/lib/Analysis/plugins/CMakeLists.txt clang/lib/Analysis/plugins/CMakeLists.txt
clang/lib/Analysis/plugins/CheckerDependencyHandling/CMakeLists.txt clang/lib/Analysis/plugins/CheckerDependencyHandling/CMakeLists.txt
clang/lib/Analysis/plugins/CheckerOptionHandling/CMakeLists.txt clang/lib/Analysis/plugins/CheckerOptionHandling/CMakeLists.txt
@ -398,6 +399,7 @@ lldb/source/Plugins/Platform/MacOSX/
lldb/source/Plugins/Platform/NetBSD/CMakeLists.txt lldb/source/Plugins/Platform/NetBSD/CMakeLists.txt
lldb/source/Plugins/Platform/OpenBSD/CMakeLists.txt lldb/source/Plugins/Platform/OpenBSD/CMakeLists.txt
lldb/source/Plugins/Platform/POSIX/CMakeLists.txt lldb/source/Plugins/Platform/POSIX/CMakeLists.txt
lldb/source/Plugins/Platform/QemuUser/CMakeLists.txt
lldb/source/Plugins/Platform/Windows/ lldb/source/Plugins/Platform/Windows/
lldb/source/Plugins/Platform/gdb-server/CMakeLists.txt lldb/source/Plugins/Platform/gdb-server/CMakeLists.txt
lldb/source/Plugins/Process/CMakeLists.txt lldb/source/Plugins/Process/CMakeLists.txt

View File

@ -1837,7 +1837,8 @@ enum class MultiVersionKind {
None, None,
Target, Target,
CPUSpecific, CPUSpecific,
CPUDispatch CPUDispatch,
TargetClones
}; };
/// Represents a function declaration or definition. /// Represents a function declaration or definition.
@ -2456,6 +2457,10 @@ class FunctionDecl : public DeclaratorDecl,
/// the target functionality. /// the target functionality.
bool isTargetMultiVersion() const; bool isTargetMultiVersion() const;
/// True if this function is a multiversioned dispatch function as a part of
/// the target-clones functionality.
bool isTargetClonesMultiVersion() const;
/// \brief Get the associated-constraints of this function declaration. /// \brief Get the associated-constraints of this function declaration.
/// Currently, this will either be a vector of size 1 containing the /// Currently, this will either be a vector of size 1 containing the
/// trailing-requires-clause or an empty vector. /// trailing-requires-clause or an empty vector.

View File

@ -352,7 +352,7 @@ class alignas(8) Decl {
DeclContext *Parent, std::size_t Extra = 0); DeclContext *Parent, std::size_t Extra = 0);
private: private:
bool AccessDeclContextSanity() const; bool AccessDeclContextCheck() const;
/// Get the module ownership kind to use for a local lexical child of \p DC, /// Get the module ownership kind to use for a local lexical child of \p DC,
/// which may be either a local or (rarely) an imported declaration. /// which may be either a local or (rarely) an imported declaration.
@ -472,11 +472,11 @@ class alignas(8) Decl {
void setAccess(AccessSpecifier AS) { void setAccess(AccessSpecifier AS) {
Access = AS; Access = AS;
assert(AccessDeclContextSanity()); assert(AccessDeclContextCheck());
} }
AccessSpecifier getAccess() const { AccessSpecifier getAccess() const {
assert(AccessDeclContextSanity()); assert(AccessDeclContextCheck());
return AccessSpecifier(Access); return AccessSpecifier(Access);
} }

View File

@ -6304,8 +6304,10 @@ class AtomicExpr : public Expr {
bool isCmpXChg() const { bool isCmpXChg() const {
return getOp() == AO__c11_atomic_compare_exchange_strong || return getOp() == AO__c11_atomic_compare_exchange_strong ||
getOp() == AO__c11_atomic_compare_exchange_weak || getOp() == AO__c11_atomic_compare_exchange_weak ||
getOp() == AO__hip_atomic_compare_exchange_strong ||
getOp() == AO__opencl_atomic_compare_exchange_strong || getOp() == AO__opencl_atomic_compare_exchange_strong ||
getOp() == AO__opencl_atomic_compare_exchange_weak || getOp() == AO__opencl_atomic_compare_exchange_weak ||
getOp() == AO__hip_atomic_compare_exchange_weak ||
getOp() == AO__atomic_compare_exchange || getOp() == AO__atomic_compare_exchange ||
getOp() == AO__atomic_compare_exchange_n; getOp() == AO__atomic_compare_exchange_n;
} }
@ -6340,6 +6342,8 @@ class AtomicExpr : public Expr {
auto Kind = auto Kind =
(Op >= AO__opencl_atomic_load && Op <= AO__opencl_atomic_fetch_max) (Op >= AO__opencl_atomic_load && Op <= AO__opencl_atomic_fetch_max)
? AtomicScopeModelKind::OpenCL ? AtomicScopeModelKind::OpenCL
: (Op >= AO__hip_atomic_load && Op <= AO__hip_atomic_fetch_max)
? AtomicScopeModelKind::HIP
: AtomicScopeModelKind::None; : AtomicScopeModelKind::None;
return AtomicScopeModel::create(Kind); return AtomicScopeModel::create(Kind);
} }

View File

@ -18,6 +18,7 @@
#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/ABI.h" #include "clang/Basic/ABI.h"
#include "clang/Basic/LLVM.h" #include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/DenseMapInfo.h"
@ -129,8 +130,12 @@ class GlobalDecl {
} }
KernelReferenceKind getKernelReferenceKind() const { KernelReferenceKind getKernelReferenceKind() const {
assert(isa<FunctionDecl>(getDecl()) && assert(((isa<FunctionDecl>(getDecl()) &&
cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() && cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>()) ||
(isa<FunctionTemplateDecl>(getDecl()) &&
cast<FunctionTemplateDecl>(getDecl())
->getTemplatedDecl()
->hasAttr<CUDAGlobalAttr>())) &&
"Decl is not a GPU kernel!"); "Decl is not a GPU kernel!");
return static_cast<KernelReferenceKind>(Value.getInt()); return static_cast<KernelReferenceKind>(Value.getInt());
} }

View File

@ -4227,8 +4227,8 @@ AST_MATCHER(VarDecl, isInitCapture) { return Node.isInitCapture(); }
/// lambdaExpr(forEachLambdaCapture( /// lambdaExpr(forEachLambdaCapture(
/// lambdaCapture(capturesVar(varDecl(hasType(isInteger())))))) /// lambdaCapture(capturesVar(varDecl(hasType(isInteger()))))))
/// will trigger two matches, binding for 'x' and 'y' respectively. /// will trigger two matches, binding for 'x' and 'y' respectively.
AST_MATCHER_P(LambdaExpr, forEachLambdaCapture, LambdaCaptureMatcher, AST_MATCHER_P(LambdaExpr, forEachLambdaCapture,
InnerMatcher) { internal::Matcher<LambdaCapture>, InnerMatcher) {
BoundNodesTreeBuilder Result; BoundNodesTreeBuilder Result;
bool Matched = false; bool Matched = false;
for (const auto &Capture : Node.captures()) { for (const auto &Capture : Node.captures()) {
@ -4655,7 +4655,8 @@ extern const internal::VariadicAllOfMatcher<LambdaCapture> lambdaCapture;
/// lambdaExpr(hasAnyCapture(lambdaCapture())) and /// lambdaExpr(hasAnyCapture(lambdaCapture())) and
/// lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(hasName("t"))))) /// lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(hasName("t")))))
/// both match `[=](){ return t; }`. /// both match `[=](){ return t; }`.
AST_MATCHER_P(LambdaExpr, hasAnyCapture, LambdaCaptureMatcher, InnerMatcher) { AST_MATCHER_P(LambdaExpr, hasAnyCapture, internal::Matcher<LambdaCapture>,
InnerMatcher) {
for (const LambdaCapture &Capture : Node.captures()) { for (const LambdaCapture &Capture : Node.captures()) {
clang::ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder); clang::ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
if (InnerMatcher.matches(Capture, Finder, &Result)) { if (InnerMatcher.matches(Capture, Finder, &Result)) {

View File

@ -515,7 +515,7 @@ class CFGTerminator {
/// of the most derived class while we're in the base class. /// of the most derived class while we're in the base class.
VirtualBaseBranch, VirtualBaseBranch,
/// Number of different kinds, for validity checks. We subtract 1 so that /// Number of different kinds, for assertions. We subtract 1 so that
/// to keep receiving compiler warnings when we don't cover all enum values /// to keep receiving compiler warnings when we don't cover all enum values
/// in a switch. /// in a switch.
NumKindsMinusOne = VirtualBaseBranch NumKindsMinusOne = VirtualBaseBranch

View File

@ -0,0 +1,134 @@
//===- DataflowAnalysis.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 base types and functions for building dataflow analyses
// that run over Control-Flow Graphs (CFGs).
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H
#include <iterator>
#include <utility>
#include <vector>
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
#include "llvm/ADT/Any.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
namespace clang {
namespace dataflow {
/// Base class template for dataflow analyses built on a single lattice type.
///
/// Requirements:
///
/// `Derived` must be derived from a specialization of this class template and
/// must provide the following public members:
/// * `LatticeT initialElement()` - returns a lattice element that models the
/// initial state of a basic block;
/// * `LatticeT transfer(const Stmt *, const LatticeT &, Environment &)` -
/// applies the analysis transfer function for a given statement and lattice
/// element.
///
/// `LatticeT` is a bounded join-semilattice that is used by `Derived` and must
/// provide the following public members:
/// * `LatticeJoinEffect join(const LatticeT &)` - joins the object and the
/// argument by computing their least upper bound, modifies the object if
/// necessary, and returns an effect indicating whether any changes were
/// made to it;
/// * `bool operator==(const LatticeT &) const` - returns true if and only if
/// the object is equal to the argument.
template <typename Derived, typename LatticeT>
class DataflowAnalysis : public TypeErasedDataflowAnalysis {
public:
/// Bounded join-semilattice that is used in the analysis.
using Lattice = LatticeT;
explicit DataflowAnalysis(ASTContext &Context) : Context(Context) {}
ASTContext &getASTContext() final { return Context; }
TypeErasedLattice typeErasedInitialElement() final {
return {static_cast<Derived *>(this)->initialElement()};
}
LatticeJoinEffect joinTypeErased(TypeErasedLattice &E1,
const TypeErasedLattice &E2) final {
Lattice &L1 = llvm::any_cast<Lattice &>(E1.Value);
const Lattice &L2 = llvm::any_cast<const Lattice &>(E2.Value);
return L1.join(L2);
}
bool isEqualTypeErased(const TypeErasedLattice &E1,
const TypeErasedLattice &E2) final {
const Lattice &L1 = llvm::any_cast<const Lattice &>(E1.Value);
const Lattice &L2 = llvm::any_cast<const Lattice &>(E2.Value);
return L1 == L2;
}
TypeErasedLattice transferTypeErased(const Stmt *Stmt,
const TypeErasedLattice &E,
Environment &Env) final {
const Lattice &L = llvm::any_cast<const Lattice &>(E.Value);
return {static_cast<Derived *>(this)->transfer(Stmt, L, Env)};
}
private:
ASTContext &Context;
};
// Model of the program at a given program point.
template <typename LatticeT> struct DataflowAnalysisState {
// Model of a program property.
LatticeT Lattice;
// Model of the state of the program (store and heap).
Environment Env;
};
/// Performs dataflow analysis and returns a mapping from basic block IDs to
/// dataflow analysis states that model the respective basic blocks. Indices
/// of the returned vector correspond to basic block IDs.
///
/// Requirements:
///
/// `Cfg` must have been built with `CFG::BuildOptions::setAllAlwaysAdd()` to
/// ensure that all sub-expressions in a basic block are evaluated.
template <typename AnalysisT>
std::vector<llvm::Optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>
runDataflowAnalysis(const CFG &Cfg, AnalysisT &Analysis,
const Environment &InitEnv) {
auto TypeErasedBlockStates =
runTypeErasedDataflowAnalysis(Cfg, Analysis, InitEnv);
std::vector<
llvm::Optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>
BlockStates;
BlockStates.reserve(TypeErasedBlockStates.size());
llvm::transform(std::move(TypeErasedBlockStates),
std::back_inserter(BlockStates), [](auto &OptState) {
return std::move(OptState).map([](auto &&State) {
return DataflowAnalysisState<typename AnalysisT::Lattice>{
llvm::any_cast<typename AnalysisT::Lattice>(
std::move(State.Lattice.Value)),
std::move(State.Env)};
});
});
return BlockStates;
}
} // namespace dataflow
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H

View File

@ -0,0 +1,27 @@
//===-- DataflowEnvironment.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 an Environment class that is used by dataflow analyses
// that run over Control-Flow Graphs (CFGs) to keep track of the state of the
// program at given program points.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H
namespace clang {
namespace dataflow {
/// Holds the state of the program (store and heap) at a given program point.
class Environment {};
} // namespace dataflow
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H

View File

@ -0,0 +1,29 @@
//===- DataflowLattice.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 base types for building lattices to be used in dataflow
// analyses that run over Control-Flow Graphs (CFGs).
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWLATTICE_H
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWLATTICE_H
namespace clang {
namespace dataflow {
/// Effect indicating whether a lattice join operation resulted in a new value.
enum class LatticeJoinEffect {
Unchanged,
Changed,
};
} // namespace dataflow
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWLATTICE_H

View File

@ -0,0 +1,95 @@
//===- TypeErasedDataflowAnalysis.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 type-erased base types and functions for building dataflow
// analyses that run over Control-Flow Graphs (CFGs).
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H
#include <vector>
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
#include "llvm/ADT/Any.h"
#include "llvm/ADT/Optional.h"
namespace clang {
namespace dataflow {
/// Type-erased lattice element container.
///
/// Requirements:
///
/// The type of the object stored in the container must be a bounded
/// join-semilattice.
struct TypeErasedLattice {
llvm::Any Value;
};
/// Type-erased base class for dataflow analyses built on a single lattice type.
class TypeErasedDataflowAnalysis {
public:
virtual ~TypeErasedDataflowAnalysis() {}
/// Returns the `ASTContext` that is used by the analysis.
virtual ASTContext &getASTContext() = 0;
/// Returns a type-erased lattice element that models the initial state of a
/// basic block.
virtual TypeErasedLattice typeErasedInitialElement() = 0;
/// Joins two type-erased lattice elements by computing their least upper
/// bound. Places the join result in the left element and returns an effect
/// indicating whether any changes were made to it.
virtual LatticeJoinEffect joinTypeErased(TypeErasedLattice &,
const TypeErasedLattice &) = 0;
/// Returns true if and only if the two given type-erased lattice elements are
/// equal.
virtual bool isEqualTypeErased(const TypeErasedLattice &,
const TypeErasedLattice &) = 0;
/// Applies the analysis transfer function for a given statement and
/// type-erased lattice element.
virtual TypeErasedLattice transferTypeErased(const Stmt *,
const TypeErasedLattice &,
Environment &) = 0;
};
/// Type-erased model of the program at a given program point.
struct TypeErasedDataflowAnalysisState {
/// Type-erased model of a program property.
TypeErasedLattice Lattice;
/// Model of the state of the program (store and heap).
Environment Env;
};
/// Performs dataflow analysis and returns a mapping from basic block IDs to
/// dataflow analysis states that model the respective basic blocks. Indices
/// of the returned vector correspond to basic block IDs.
///
/// Requirements:
///
/// `Cfg` must have been built with `CFG::BuildOptions::setAllAlwaysAdd()` to
/// ensure that all sub-expressions in a basic block are evaluated.
std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>>
runTypeErasedDataflowAnalysis(const CFG &Cfg,
TypeErasedDataflowAnalysis &Analysis,
const Environment &InitEnv);
} // namespace dataflow
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H

View File

@ -2677,6 +2677,40 @@ def Target : InheritableAttr {
}]; }];
} }
def TargetClones : InheritableAttr {
let Spellings = [GCC<"target_clones">];
let Args = [VariadicStringArgument<"featuresStrs">];
let Documentation = [TargetClonesDocs];
let Subjects = SubjectList<[Function], ErrorDiag>;
let AdditionalMembers = [{
StringRef getFeatureStr(unsigned Index) const {
return *(featuresStrs_begin() + Index);
}
// 'default' is always moved to the end, so it isn't considered
// when mangling the index.
unsigned getMangledIndex(unsigned Index) const {
if (getFeatureStr(Index) == "default")
return std::count_if(featuresStrs_begin(), featuresStrs_end(),
[](StringRef S) { return S != "default"; });
return std::count_if(featuresStrs_begin(), featuresStrs_begin() + Index,
[](StringRef S) { return S != "default"; });
}
// True if this is the first of this version to appear in the config string.
// This is used to make sure we don't try to emit this function multiple
// times.
bool isFirstOfVersion(unsigned Index) const {
StringRef FeatureStr(getFeatureStr(Index));
return 0 == std::count_if(
featuresStrs_begin(), featuresStrs_begin() + Index,
[FeatureStr](StringRef S) { return S == FeatureStr; });
}
}];
}
def : MutualExclusions<[TargetClones, Target, CPUDispatch, CPUSpecific]>;
def MinVectorWidth : InheritableAttr { def MinVectorWidth : InheritableAttr {
let Spellings = [Clang<"min_vector_width">]; let Spellings = [Clang<"min_vector_width">];
let Args = [UnsignedArgument<"VectorWidth">]; let Args = [UnsignedArgument<"VectorWidth">];

View File

@ -2233,6 +2233,40 @@ Additionally, a function may not become multiversioned after its first use.
}]; }];
} }
def TargetClonesDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Clang supports the ``target_clones("OPTIONS")`` attribute. This attribute may be
attached to a function declaration and causes function multiversioning, where
multiple versions of the function will be emitted with different code
generation options. Additionally, these versions will be resolved at runtime
based on the priority of their attribute options. All ``target_clone`` functions
are considered multiversioned functions.
All multiversioned functions must contain a ``default`` (fallback)
implementation, otherwise usages of the function are considered invalid.
Additionally, a function may not become multiversioned after its first use.
The options to ``target_clones`` can either be a target-specific architecture
(specified as ``arch=CPU``), or one of a list of subtarget features.
Example "subtarget features" from the x86 backend include: "mmx", "sse", "sse4.2",
"avx", "xop" and largely correspond to the machine specific options handled by
the front end.
The versions can either be listed as a comma-separated sequence of string
literals or as a single string literal containing a comma-separated list of
versions. For compatibility with GCC, the two formats can be mixed. For
example, the following will emit 4 versions of the function:
.. code-block:: c++
__attribute__((target_clones("arch=atom,avx2","arch=ivybridge","default")))
void foo() {}
}];
}
def MinVectorWidthDocs : Documentation { def MinVectorWidthDocs : Documentation {
let Category = DocCatFunction; let Category = DocCatFunction;
let Content = [{ let Content = [{

View File

@ -854,6 +854,19 @@ ATOMIC_BUILTIN(__opencl_atomic_fetch_max, "v.", "t")
ATOMIC_BUILTIN(__atomic_fetch_min, "v.", "t") ATOMIC_BUILTIN(__atomic_fetch_min, "v.", "t")
ATOMIC_BUILTIN(__atomic_fetch_max, "v.", "t") ATOMIC_BUILTIN(__atomic_fetch_max, "v.", "t")
// HIP atomic builtins.
ATOMIC_BUILTIN(__hip_atomic_load, "v.", "t")
ATOMIC_BUILTIN(__hip_atomic_store, "v.", "t")
ATOMIC_BUILTIN(__hip_atomic_compare_exchange_weak, "v.", "t")
ATOMIC_BUILTIN(__hip_atomic_compare_exchange_strong, "v.", "t")
ATOMIC_BUILTIN(__hip_atomic_exchange, "v.", "t")
ATOMIC_BUILTIN(__hip_atomic_fetch_add, "v.", "t")
ATOMIC_BUILTIN(__hip_atomic_fetch_and, "v.", "t")
ATOMIC_BUILTIN(__hip_atomic_fetch_or, "v.", "t")
ATOMIC_BUILTIN(__hip_atomic_fetch_xor, "v.", "t")
ATOMIC_BUILTIN(__hip_atomic_fetch_min, "v.", "t")
ATOMIC_BUILTIN(__hip_atomic_fetch_max, "v.", "t")
#undef ATOMIC_BUILTIN #undef ATOMIC_BUILTIN
// Non-overloaded atomic builtins. // Non-overloaded atomic builtins.

View File

@ -404,6 +404,7 @@ BUILTIN(__builtin_altivec_vbpermd, "V2ULLiV2ULLiV16Uc", "")
// P8 Crypto built-ins. // P8 Crypto built-ins.
BUILTIN(__builtin_altivec_crypto_vsbox, "V2ULLiV2ULLi", "") BUILTIN(__builtin_altivec_crypto_vsbox, "V2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_crypto_vpermxor, "V16UcV16UcV16UcV16Uc", "") BUILTIN(__builtin_altivec_crypto_vpermxor, "V16UcV16UcV16UcV16Uc", "")
BUILTIN(__builtin_altivec_crypto_vpermxor_be, "V16UcV16UcV16UcV16Uc", "")
BUILTIN(__builtin_altivec_crypto_vshasigmaw, "V4UiV4UiIiIi", "") BUILTIN(__builtin_altivec_crypto_vshasigmaw, "V4UiV4UiIiIi", "")
BUILTIN(__builtin_altivec_crypto_vshasigmad, "V2ULLiV2ULLiIiIi", "") BUILTIN(__builtin_altivec_crypto_vshasigmad, "V2ULLiV2ULLiIiIi", "")
BUILTIN(__builtin_altivec_crypto_vcipher, "V2ULLiV2ULLiV2ULLi", "") BUILTIN(__builtin_altivec_crypto_vcipher, "V2ULLiV2ULLiV2ULLi", "")
@ -424,6 +425,12 @@ BUILTIN(__builtin_altivec_vctzh, "V8UsV8Us", "")
BUILTIN(__builtin_altivec_vctzw, "V4UiV4Ui", "") BUILTIN(__builtin_altivec_vctzw, "V4UiV4Ui", "")
BUILTIN(__builtin_altivec_vctzd, "V2ULLiV2ULLi", "") BUILTIN(__builtin_altivec_vctzd, "V2ULLiV2ULLi", "")
// P8 BCD builtins.
BUILTIN(__builtin_ppc_bcdadd, "V16UcV16UcV16UcIi", "")
BUILTIN(__builtin_ppc_bcdsub, "V16UcV16UcV16UcIi", "")
BUILTIN(__builtin_ppc_bcdadd_p, "iiV16UcV16Uc", "")
BUILTIN(__builtin_ppc_bcdsub_p, "iiV16UcV16Uc", "")
BUILTIN(__builtin_altivec_vclzlsbb, "SiV16Uc", "") BUILTIN(__builtin_altivec_vclzlsbb, "SiV16Uc", "")
BUILTIN(__builtin_altivec_vctzlsbb, "SiV16Uc", "") BUILTIN(__builtin_altivec_vctzlsbb, "SiV16Uc", "")
BUILTIN(__builtin_altivec_vprtybw, "V4UiV4Ui", "") BUILTIN(__builtin_altivec_vprtybw, "V4UiV4Ui", "")

View File

@ -189,6 +189,12 @@ def err_drv_invalid_mtp : Error<
"invalid thread pointer reading mode '%0'">; "invalid thread pointer reading mode '%0'">;
def err_drv_missing_arg_mtp : Error< def err_drv_missing_arg_mtp : Error<
"missing argument to '%0'">; "missing argument to '%0'">;
def warn_drv_missing_plugin_name : Warning<
"missing plugin name in %0">,
InGroup<InvalidCommandLineArgument>;
def warn_drv_missing_plugin_arg : Warning<
"missing plugin argument for plugin %0 in %1">,
InGroup<InvalidCommandLineArgument>;
def err_drv_invalid_libcxx_deployment : Error< def err_drv_invalid_libcxx_deployment : Error<
"invalid deployment target for -stdlib=libc++ (requires %0 or later)">; "invalid deployment target for -stdlib=libc++ (requires %0 or later)">;
def err_drv_invalid_argument_to_option : Error< def err_drv_invalid_argument_to_option : Error<
@ -394,6 +400,8 @@ def warn_ignoring_verify_debuginfo_preserve_export : Warning<
InGroup<UnusedCommandLineArgument>; InGroup<UnusedCommandLineArgument>;
def err_invalid_branch_protection: Error < def err_invalid_branch_protection: Error <
"invalid branch protection option '%0' in '%1'">; "invalid branch protection option '%0' in '%1'">;
def warn_unsupported_branch_protection: Warning <
"invalid branch protection option '%0' in '%1'">, InGroup<BranchProtection>;
def err_invalid_sls_hardening : Error< def err_invalid_sls_hardening : Error<
"invalid sls hardening option '%0' in '%1'">; "invalid sls hardening option '%0' in '%1'">;
def err_sls_hardening_arm_not_supported : Error< def err_sls_hardening_arm_not_supported : Error<

View File

@ -56,7 +56,9 @@ def CoroutineMissingUnhandledException :
DiagGroup<"coroutine-missing-unhandled-exception">; DiagGroup<"coroutine-missing-unhandled-exception">;
def DeprecatedExperimentalCoroutine : def DeprecatedExperimentalCoroutine :
DiagGroup<"deprecated-experimental-coroutine">; DiagGroup<"deprecated-experimental-coroutine">;
def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException, DeprecatedExperimentalCoroutine]>; def DeprecatedCoroutine :
DiagGroup<"deprecated-coroutine", [DeprecatedExperimentalCoroutine]>;
def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException, DeprecatedCoroutine]>;
def ObjCBoolConstantConversion : DiagGroup<"objc-bool-constant-conversion">; def ObjCBoolConstantConversion : DiagGroup<"objc-bool-constant-conversion">;
def ConstantConversion : DiagGroup<"constant-conversion", def ConstantConversion : DiagGroup<"constant-conversion",
[BitFieldConstantConversion, [BitFieldConstantConversion,
@ -1273,9 +1275,14 @@ def : DiagGroup<"spirv-compat", [SpirCompat]>; // Alias.
// Warning for the GlobalISel options. // Warning for the GlobalISel options.
def GlobalISel : DiagGroup<"global-isel">; def GlobalISel : DiagGroup<"global-isel">;
// A warning group for the GNU extension to allow mixed specifier types for
// target-clones multiversioning.
def TargetClonesMixedSpecifiers : DiagGroup<"target-clones-mixed-specifiers">;
// A warning group specifically for warnings related to function // A warning group specifically for warnings related to function
// multiversioning. // multiversioning.
def FunctionMultiVersioning : DiagGroup<"function-multiversion">; def FunctionMultiVersioning
: DiagGroup<"function-multiversion", [TargetClonesMixedSpecifiers]>;
def NoDeref : DiagGroup<"noderef">; def NoDeref : DiagGroup<"noderef">;
@ -1331,3 +1338,6 @@ def PedanticMacros : DiagGroup<"pedantic-macros",
BuiltinMacroRedefined, BuiltinMacroRedefined,
RestrictExpansionMacro, RestrictExpansionMacro,
FinalMacro]>; FinalMacro]>;
def BranchProtection : DiagGroup<"branch-protection">;

View File

@ -30,7 +30,7 @@ namespace clang {
// Size of each of the diagnostic categories. // Size of each of the diagnostic categories.
enum { enum {
DIAG_SIZE_COMMON = 300, DIAG_SIZE_COMMON = 300,
DIAG_SIZE_DRIVER = 250, DIAG_SIZE_DRIVER = 300,
DIAG_SIZE_FRONTEND = 150, DIAG_SIZE_FRONTEND = 150,
DIAG_SIZE_SERIALIZATION = 120, DIAG_SIZE_SERIALIZATION = 120,
DIAG_SIZE_LEX = 400, DIAG_SIZE_LEX = 400,

View File

@ -1548,6 +1548,9 @@ def note_meant_to_use_typename : Note<
let CategoryName = "Coroutines Issue" in { let CategoryName = "Coroutines Issue" in {
def err_for_co_await_not_range_for : Error< def err_for_co_await_not_range_for : Error<
"'co_await' modifier can only be applied to range-based for loop">; "'co_await' modifier can only be applied to range-based for loop">;
def warn_deprecated_for_co_await : Warning<
"'for co_await' belongs to CoroutineTS instead of C++20, which is deprecated">,
InGroup<DeprecatedCoroutine>;
} }
let CategoryName = "Concepts Issue" in { let CategoryName = "Concepts Issue" in {

View File

@ -2979,9 +2979,13 @@ def err_attribute_requires_opencl_version : Error<
"attribute %0 is supported in the OpenCL version %1%select{| onwards}2">; "attribute %0 is supported in the OpenCL version %1%select{| onwards}2">;
def err_invalid_branch_protection_spec : Error< def err_invalid_branch_protection_spec : Error<
"invalid or misplaced branch protection specification '%0'">; "invalid or misplaced branch protection specification '%0'">;
def warn_unsupported_branch_protection_spec : Warning<
"unsupported branch protection specification '%0'">, InGroup<BranchProtection>;
def warn_unsupported_target_attribute def warn_unsupported_target_attribute
: Warning<"%select{unsupported|duplicate|unknown}0%select{| architecture|" : Warning<"%select{unsupported|duplicate|unknown}0%select{| architecture|"
" tune CPU}1 '%2' in the 'target' attribute string; 'target' " " tune CPU}1 '%2' in the '%select{target|target_clones}3' "
"attribute string; '%select{target|target_clones}3' "
"attribute ignored">, "attribute ignored">,
InGroup<IgnoredAttributes>; InGroup<IgnoredAttributes>;
def err_attribute_unsupported def err_attribute_unsupported
@ -9864,6 +9868,8 @@ def warn_duplicate_attribute_exact : Warning<
def warn_duplicate_attribute : Warning< def warn_duplicate_attribute : Warning<
"attribute %0 is already applied with different arguments">, "attribute %0 is already applied with different arguments">,
InGroup<IgnoredAttributes>; InGroup<IgnoredAttributes>;
def err_disallowed_duplicate_attribute : Error<
"attribute %0 cannot appear more than once on a declaration">;
def warn_sync_fetch_and_nand_semantics_change : Warning< def warn_sync_fetch_and_nand_semantics_change : Warning<
"the semantics of this intrinsic changed with GCC " "the semantics of this intrinsic changed with GCC "
@ -11254,9 +11260,11 @@ def err_multiversion_duplicate : Error<
"multiversioned function redeclarations require identical target attributes">; "multiversioned function redeclarations require identical target attributes">;
def err_multiversion_noproto : Error< def err_multiversion_noproto : Error<
"multiversioned function must have a prototype">; "multiversioned function must have a prototype">;
def err_multiversion_disallowed_other_attr : Error< def err_multiversion_disallowed_other_attr
"attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioning cannot be combined" : Error<"attribute "
" with attribute %1">; "'%select{|target|cpu_specific|cpu_dispatch|target_clones}0' "
"multiversioning cannot be combined"
" with attribute %1">;
def err_multiversion_mismatched_attrs def err_multiversion_mismatched_attrs
: Error<"attributes on multiversioned functions must all match, attribute " : Error<"attributes on multiversioned functions must all match, attribute "
"%0 %select{is missing|has different arguments}1">; "%0 %select{is missing|has different arguments}1">;
@ -11264,11 +11272,14 @@ def err_multiversion_diff : Error<
"multiversioned function declaration has a different %select{calling convention" "multiversioned function declaration has a different %select{calling convention"
"|return type|constexpr specification|inline specification|linkage|" "|return type|constexpr specification|inline specification|linkage|"
"language linkage}0">; "language linkage}0">;
def err_multiversion_doesnt_support : Error< def err_multiversion_doesnt_support
"attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioned functions do not " : Error<"attribute "
"yet support %select{function templates|virtual functions|" "'%select{|target|cpu_specific|cpu_dispatch|target_clones}0' "
"deduced return types|constructors|destructors|deleted functions|" "multiversioned functions do not "
"defaulted functions|constexpr functions|consteval function}1">; "yet support %select{function templates|virtual functions|"
"deduced return types|constructors|destructors|deleted functions|"
"defaulted functions|constexpr functions|consteval "
"function|lambdas}1">;
def err_multiversion_not_allowed_on_main : Error< def err_multiversion_not_allowed_on_main : Error<
"'main' cannot be a multiversioned function">; "'main' cannot be a multiversioned function">;
def err_multiversion_not_supported : Error< def err_multiversion_not_supported : Error<
@ -11285,6 +11296,19 @@ def warn_multiversion_duplicate_entries : Warning<
def warn_dispatch_body_ignored : Warning< def warn_dispatch_body_ignored : Warning<
"body of cpu_dispatch function will be ignored">, "body of cpu_dispatch function will be ignored">,
InGroup<FunctionMultiVersioning>; InGroup<FunctionMultiVersioning>;
def err_target_clone_must_have_default
: Error<"'target_clones' multiversioning requires a default target">;
def err_target_clone_doesnt_match
: Error<"'target_clones' attribute does not match previous declaration">;
def warn_target_clone_mixed_values
: ExtWarn<
"mixing 'target_clones' specifier mechanisms is permitted for GCC "
"compatibility; use a comma separated sequence of string literals, "
"or a string literal containing a comma-separated list of versions">,
InGroup<TargetClonesMixedSpecifiers>;
def warn_target_clone_duplicate_options
: Warning<"version list contains duplicate entries">,
InGroup<FunctionMultiVersioning>;
// three-way comparison operator diagnostics // three-way comparison operator diagnostics
def err_implied_comparison_category_type_not_found : Error< def err_implied_comparison_category_type_not_found : Error<

View File

@ -40,6 +40,11 @@ namespace clang {
/// Update getAsString. /// Update getAsString.
/// ///
enum class SyncScope { enum class SyncScope {
HIPSingleThread,
HIPWavefront,
HIPWorkgroup,
HIPAgent,
HIPSystem,
OpenCLWorkGroup, OpenCLWorkGroup,
OpenCLDevice, OpenCLDevice,
OpenCLAllSVMDevices, OpenCLAllSVMDevices,
@ -49,6 +54,16 @@ enum class SyncScope {
inline llvm::StringRef getAsString(SyncScope S) { inline llvm::StringRef getAsString(SyncScope S) {
switch (S) { switch (S) {
case SyncScope::HIPSingleThread:
return "hip_singlethread";
case SyncScope::HIPWavefront:
return "hip_wavefront";
case SyncScope::HIPWorkgroup:
return "hip_workgroup";
case SyncScope::HIPAgent:
return "hip_agent";
case SyncScope::HIPSystem:
return "hip_system";
case SyncScope::OpenCLWorkGroup: case SyncScope::OpenCLWorkGroup:
return "opencl_workgroup"; return "opencl_workgroup";
case SyncScope::OpenCLDevice: case SyncScope::OpenCLDevice:
@ -62,7 +77,7 @@ inline llvm::StringRef getAsString(SyncScope S) {
} }
/// Defines the kind of atomic scope models. /// Defines the kind of atomic scope models.
enum class AtomicScopeModelKind { None, OpenCL }; enum class AtomicScopeModelKind { None, OpenCL, HIP };
/// Defines the interface for synch scope model. /// Defines the interface for synch scope model.
class AtomicScopeModel { class AtomicScopeModel {
@ -138,6 +153,58 @@ class AtomicScopeOpenCLModel : public AtomicScopeModel {
} }
}; };
/// Defines the synch scope model for HIP.
class AtomicScopeHIPModel : public AtomicScopeModel {
public:
/// The enum values match the pre-defined macros
/// __HIP_MEMORY_SCOPE_*, which are used to define memory_scope_*
/// enums in hip-c.h.
enum ID {
SingleThread = 1,
Wavefront = 2,
Workgroup = 3,
Agent = 4,
System = 5,
Last = System
};
AtomicScopeHIPModel() {}
SyncScope map(unsigned S) const override {
switch (static_cast<ID>(S)) {
case SingleThread:
return SyncScope::HIPSingleThread;
case Wavefront:
return SyncScope::HIPWavefront;
case Workgroup:
return SyncScope::HIPWorkgroup;
case Agent:
return SyncScope::HIPAgent;
case System:
return SyncScope::HIPSystem;
}
llvm_unreachable("Invalid language synch scope value");
}
bool isValid(unsigned S) const override {
return S >= static_cast<unsigned>(SingleThread) &&
S <= static_cast<unsigned>(Last);
}
ArrayRef<unsigned> getRuntimeValues() const override {
static_assert(Last == System, "Does not include all synch scopes");
static const unsigned Scopes[] = {
static_cast<unsigned>(SingleThread), static_cast<unsigned>(Wavefront),
static_cast<unsigned>(Workgroup), static_cast<unsigned>(Agent),
static_cast<unsigned>(System)};
return llvm::makeArrayRef(Scopes);
}
unsigned getFallBackValue() const override {
return static_cast<unsigned>(System);
}
};
inline std::unique_ptr<AtomicScopeModel> inline std::unique_ptr<AtomicScopeModel>
AtomicScopeModel::create(AtomicScopeModelKind K) { AtomicScopeModel::create(AtomicScopeModelKind K) {
switch (K) { switch (K) {
@ -145,9 +212,11 @@ AtomicScopeModel::create(AtomicScopeModelKind K) {
return std::unique_ptr<AtomicScopeModel>{}; return std::unique_ptr<AtomicScopeModel>{};
case AtomicScopeModelKind::OpenCL: case AtomicScopeModelKind::OpenCL:
return std::make_unique<AtomicScopeOpenCLModel>(); return std::make_unique<AtomicScopeOpenCLModel>();
case AtomicScopeModelKind::HIP:
return std::make_unique<AtomicScopeHIPModel>();
} }
llvm_unreachable("Invalid atomic scope model kind"); llvm_unreachable("Invalid atomic scope model kind");
} }
} } // namespace clang
#endif #endif

View File

@ -2504,6 +2504,9 @@ defm rwpi : BoolFOption<"rwpi",
NegFlag<SetFalse>>; NegFlag<SetFalse>>;
def fplugin_EQ : Joined<["-"], "fplugin=">, Group<f_Group>, Flags<[NoXarchOption]>, MetaVarName<"<dsopath>">, def fplugin_EQ : Joined<["-"], "fplugin=">, Group<f_Group>, Flags<[NoXarchOption]>, MetaVarName<"<dsopath>">,
HelpText<"Load the named plugin (dynamic shared object)">; HelpText<"Load the named plugin (dynamic shared object)">;
def fplugin_arg : Joined<["-"], "fplugin-arg-">,
MetaVarName<"<name>-<arg>">,
HelpText<"Pass <arg> to plugin <name>">;
def fpass_plugin_EQ : Joined<["-"], "fpass-plugin=">, def fpass_plugin_EQ : Joined<["-"], "fpass-plugin=">,
Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<dsopath>">, Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<dsopath>">,
HelpText<"Load pass plugin from a dynamic shared object file (only with new pass manager).">, HelpText<"Load pass plugin from a dynamic shared object file (only with new pass manager).">,
@ -2786,10 +2789,11 @@ def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group<f_Group>
def fvisibility_global_new_delete_hidden : Flag<["-"], "fvisibility-global-new-delete-hidden">, Group<f_Group>, def fvisibility_global_new_delete_hidden : Flag<["-"], "fvisibility-global-new-delete-hidden">, Group<f_Group>,
HelpText<"Give global C++ operator new and delete declarations hidden visibility">, Flags<[CC1Option]>, HelpText<"Give global C++ operator new and delete declarations hidden visibility">, Flags<[CC1Option]>,
MarshallingInfoFlag<LangOpts<"GlobalAllocationFunctionVisibilityHidden">>; MarshallingInfoFlag<LangOpts<"GlobalAllocationFunctionVisibilityHidden">>;
def fnew_infallible : Flag<["-"], "fnew-infallible">, Group<f_Group>, defm new_infallible : BoolFOption<"new-infallible",
HelpText<"Treats throwing global C++ operator new as always returning valid memory " LangOpts<"NewInfallible">, DefaultFalse,
"(annotates with __attribute__((returns_nonnull)) and throw()). This is detectable in source.">, PosFlag<SetTrue, [], "Enable">, NegFlag<SetFalse, [], "Disable">,
Flags<[CC1Option]>, MarshallingInfoFlag<LangOpts<"NewInfallible">>; BothFlags<[CC1Option], " treating throwing global C++ operator new as always returning valid memory "
"(annotates with __attribute__((returns_nonnull)) and throw()). This is detectable in source.">>;
defm whole_program_vtables : BoolFOption<"whole-program-vtables", defm whole_program_vtables : BoolFOption<"whole-program-vtables",
CodeGenOpts<"WholeProgramVTables">, DefaultFalse, CodeGenOpts<"WholeProgramVTables">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Enables whole-program vtable optimization. Requires -flto">, PosFlag<SetTrue, [CC1Option], "Enables whole-program vtable optimization. Requires -flto">,
@ -4519,7 +4523,7 @@ def frecord_marker_EQ : Joined<["-"], "frecord-marker=">, Group<gfortran_Group>;
defm aggressive_function_elimination : BooleanFFlag<"aggressive-function-elimination">, Group<gfortran_Group>; defm aggressive_function_elimination : BooleanFFlag<"aggressive-function-elimination">, Group<gfortran_Group>;
defm align_commons : BooleanFFlag<"align-commons">, Group<gfortran_Group>; defm align_commons : BooleanFFlag<"align-commons">, Group<gfortran_Group>;
defm all_intrinsics : BooleanFFlag<"all-intrinsics">, Group<gfortran_Group>; defm all_intrinsics : BooleanFFlag<"all-intrinsics">, Group<gfortran_Group>;
defm automatic : BooleanFFlag<"automatic">, Group<gfortran_Group>; def fautomatic : Flag<["-"], "fautomatic">; // -fno-automatic is significant
defm backtrace : BooleanFFlag<"backtrace">, Group<gfortran_Group>; defm backtrace : BooleanFFlag<"backtrace">, Group<gfortran_Group>;
defm bounds_check : BooleanFFlag<"bounds-check">, Group<gfortran_Group>; defm bounds_check : BooleanFFlag<"bounds-check">, Group<gfortran_Group>;
defm check_array_temporaries : BooleanFFlag<"check-array-temporaries">, Group<gfortran_Group>; defm check_array_temporaries : BooleanFFlag<"check-array-temporaries">, Group<gfortran_Group>;
@ -4616,6 +4620,9 @@ defm backslash : OptInFC1FFlag<"backslash", "Specify that backslash in string in
defm xor_operator : OptInFC1FFlag<"xor-operator", "Enable .XOR. as a synonym of .NEQV.">; defm xor_operator : OptInFC1FFlag<"xor-operator", "Enable .XOR. as a synonym of .NEQV.">;
defm logical_abbreviations : OptInFC1FFlag<"logical-abbreviations", "Enable logical abbreviations">; defm logical_abbreviations : OptInFC1FFlag<"logical-abbreviations", "Enable logical abbreviations">;
defm implicit_none : OptInFC1FFlag<"implicit-none", "No implicit typing allowed unless overridden by IMPLICIT statements">; defm implicit_none : OptInFC1FFlag<"implicit-none", "No implicit typing allowed unless overridden by IMPLICIT statements">;
def fno_automatic : Flag<["-"], "fno-automatic">, Group<f_Group>,
HelpText<"Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE">;
} }
def J : JoinedOrSeparate<["-"], "J">, def J : JoinedOrSeparate<["-"], "J">,
@ -5059,9 +5066,10 @@ def msmall_data_limit : Separate<["-"], "msmall-data-limit">,
def funwind_tables_EQ : Joined<["-"], "funwind-tables=">, def funwind_tables_EQ : Joined<["-"], "funwind-tables=">,
HelpText<"Generate unwinding tables for all functions">, HelpText<"Generate unwinding tables for all functions">,
MarshallingInfoInt<CodeGenOpts<"UnwindTables">>; MarshallingInfoInt<CodeGenOpts<"UnwindTables">>;
def mconstructor_aliases : Flag<["-"], "mconstructor-aliases">, defm constructor_aliases : BoolOption<"m", "constructor-aliases",
HelpText<"Emit complete constructors and destructors as aliases when possible">, CodeGenOpts<"CXXCtorDtorAliases">, DefaultFalse,
MarshallingInfoFlag<CodeGenOpts<"CXXCtorDtorAliases">>; PosFlag<SetTrue, [], "Enable">, NegFlag<SetFalse, [], "Disable">,
BothFlags<[CC1Option], " emitting complete constructors and destructors as aliases when possible">>;
def mlink_bitcode_file : Separate<["-"], "mlink-bitcode-file">, def mlink_bitcode_file : Separate<["-"], "mlink-bitcode-file">,
HelpText<"Link the given bitcode file before performing optimizations.">; HelpText<"Link the given bitcode file before performing optimizations.">;
def mlink_builtin_bitcode : Separate<["-"], "mlink-builtin-bitcode">, def mlink_builtin_bitcode : Separate<["-"], "mlink-builtin-bitcode">,
@ -5174,10 +5182,6 @@ defm debug_pass_manager : BoolOption<"f", "debug-pass-manager",
CodeGenOpts<"DebugPassManager">, DefaultFalse, CodeGenOpts<"DebugPassManager">, DefaultFalse,
PosFlag<SetTrue, [], "Prints debug information for the new pass manager">, PosFlag<SetTrue, [], "Prints debug information for the new pass manager">,
NegFlag<SetFalse, [], "Disables debug printing for the new pass manager">>; NegFlag<SetFalse, [], "Disables debug printing for the new pass manager">>;
def fexperimental_debug_variable_locations : Flag<["-"],
"fexperimental-debug-variable-locations">,
HelpText<"Use experimental new value-tracking variable locations">,
MarshallingInfoFlag<CodeGenOpts<"ValueTrackingVariableLocations">>;
def fverify_debuginfo_preserve def fverify_debuginfo_preserve
: Flag<["-"], "fverify-debuginfo-preserve">, : Flag<["-"], "fverify-debuginfo-preserve">,
HelpText<"Enable Debug Info Metadata preservation testing in " HelpText<"Enable Debug Info Metadata preservation testing in "

View File

@ -274,7 +274,7 @@ class PreambleCallbacks {
public: public:
virtual ~PreambleCallbacks() = default; virtual ~PreambleCallbacks() = default;
/// Called before FrontendAction::BeginSourceFile. /// Called before FrontendAction::Execute.
/// Can be used to store references to various CompilerInstance fields /// Can be used to store references to various CompilerInstance fields
/// (e.g. SourceManager) that may be interesting to the consumers of other /// (e.g. SourceManager) that may be interesting to the consumers of other
/// callbacks. /// callbacks.
@ -291,7 +291,7 @@ class PreambleCallbacks {
/// used instead, but having only this method allows a simpler API. /// used instead, but having only this method allows a simpler API.
virtual void HandleTopLevelDecl(DeclGroupRef DG); virtual void HandleTopLevelDecl(DeclGroupRef DG);
/// Creates wrapper class for PPCallbacks so we can also process information /// Creates wrapper class for PPCallbacks so we can also process information
/// about includes that are inside of a preamble /// about includes that are inside of a preamble. Called after BeforeExecute.
virtual std::unique_ptr<PPCallbacks> createPPCallbacks(); virtual std::unique_ptr<PPCallbacks> createPPCallbacks();
/// The returned CommentHandler will be added to the preprocessor if not null. /// The returned CommentHandler will be added to the preprocessor if not null.
virtual CommentHandler *getCommentHandler(); virtual CommentHandler *getCommentHandler();

View File

@ -1296,6 +1296,11 @@ class Sema final {
EK_Decltype, EK_TemplateArgument, EK_Other EK_Decltype, EK_TemplateArgument, EK_Other
} ExprContext; } ExprContext;
// A context can be nested in both a discarded statement context and
// an immediate function context, so they need to be tracked independently.
bool InDiscardedStatement;
bool InImmediateFunctionContext;
ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
unsigned NumCleanupObjects, unsigned NumCleanupObjects,
CleanupInfo ParentCleanup, CleanupInfo ParentCleanup,
@ -1303,7 +1308,8 @@ class Sema final {
ExpressionKind ExprContext) ExpressionKind ExprContext)
: Context(Context), ParentCleanup(ParentCleanup), : Context(Context), ParentCleanup(ParentCleanup),
NumCleanupObjects(NumCleanupObjects), NumTypos(0), NumCleanupObjects(NumCleanupObjects), NumTypos(0),
ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext) {} ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext),
InDiscardedStatement(false), InImmediateFunctionContext(false) {}
bool isUnevaluated() const { bool isUnevaluated() const {
return Context == ExpressionEvaluationContext::Unevaluated || return Context == ExpressionEvaluationContext::Unevaluated ||
@ -1317,7 +1323,13 @@ class Sema final {
} }
bool isImmediateFunctionContext() const { bool isImmediateFunctionContext() const {
return Context == ExpressionEvaluationContext::ImmediateFunctionContext; return Context == ExpressionEvaluationContext::ImmediateFunctionContext ||
InImmediateFunctionContext;
}
bool isDiscardedStatementContext() const {
return Context == ExpressionEvaluationContext::DiscardedStatement ||
InDiscardedStatement;
} }
}; };
@ -4351,6 +4363,10 @@ class Sema final {
llvm::Error isValidSectionSpecifier(StringRef Str); llvm::Error isValidSectionSpecifier(StringRef Str);
bool checkSectionName(SourceLocation LiteralLoc, StringRef Str); bool checkSectionName(SourceLocation LiteralLoc, StringRef Str);
bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str); bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);
bool checkTargetClonesAttrString(SourceLocation LiteralLoc, StringRef Str,
const StringLiteral *Literal,
bool &HasDefault, bool &HasCommas,
SmallVectorImpl<StringRef> &Strings);
bool checkMSInheritanceAttrOnDefinition( bool checkMSInheritanceAttrOnDefinition(
CXXRecordDecl *RD, SourceRange Range, bool BestCase, CXXRecordDecl *RD, SourceRange Range, bool BestCase,
MSInheritanceModel SemanticSpelling); MSInheritanceModel SemanticSpelling);
@ -9150,14 +9166,7 @@ class Sema final {
bool isImmediateFunctionContext() const { bool isImmediateFunctionContext() const {
assert(!ExprEvalContexts.empty() && assert(!ExprEvalContexts.empty() &&
"Must be in an expression evaluation context"); "Must be in an expression evaluation context");
for (const ExpressionEvaluationContextRecord &context : return ExprEvalContexts.back().isImmediateFunctionContext();
llvm::reverse(ExprEvalContexts)) {
if (context.isImmediateFunctionContext())
return true;
if (context.isUnevaluated())
return false;
}
return false;
} }
/// RAII class used to determine whether SFINAE has /// RAII class used to determine whether SFINAE has

View File

@ -195,15 +195,23 @@ class DependencyScanningWorkerFilesystem : public llvm::vfs::ProxyFileSystem {
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>> llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
openFileForRead(const Twine &Path) override; openFileForRead(const Twine &Path) override;
void clearIgnoredFiles() { IgnoredFiles.clear(); } /// Disable minimization of the given file.
void ignoreFile(StringRef Filename); void disableMinimization(StringRef Filename);
/// Enable minimization of all files.
void enableMinimizationOfAllFiles() { NotToBeMinimized.clear(); }
private: private:
bool shouldIgnoreFile(StringRef Filename); /// Check whether the file should be minimized.
bool shouldMinimize(StringRef Filename);
llvm::ErrorOr<const CachedFileSystemEntry *> llvm::ErrorOr<const CachedFileSystemEntry *>
getOrCreateFileSystemEntry(const StringRef Filename); getOrCreateFileSystemEntry(const StringRef Filename);
/// Create a cached file system entry based on the initial status result.
CachedFileSystemEntry
createFileSystemEntry(llvm::ErrorOr<llvm::vfs::Status> &&MaybeStatus,
StringRef Filename, bool ShouldMinimize);
/// The global cache shared between worker threads. /// The global cache shared between worker threads.
DependencyScanningFilesystemSharedCache &SharedCache; DependencyScanningFilesystemSharedCache &SharedCache;
/// The local cache is used by the worker thread to cache file system queries /// The local cache is used by the worker thread to cache file system queries
@ -214,7 +222,7 @@ class DependencyScanningWorkerFilesystem : public llvm::vfs::ProxyFileSystem {
/// currently active preprocessor. /// currently active preprocessor.
ExcludedPreprocessorDirectiveSkipMapping *PPSkipMappings; ExcludedPreprocessorDirectiveSkipMapping *PPSkipMappings;
/// The set of files that should not be minimized. /// The set of files that should not be minimized.
llvm::StringSet<> IgnoredFiles; llvm::StringSet<> NotToBeMinimized;
}; };
} // end namespace dependencies } // end namespace dependencies

View File

@ -11798,6 +11798,15 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
Target->getTargetOpts().FeaturesAsWritten.begin(), Target->getTargetOpts().FeaturesAsWritten.begin(),
Target->getTargetOpts().FeaturesAsWritten.end()); Target->getTargetOpts().FeaturesAsWritten.end());
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features); Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
} else if (const auto *TC = FD->getAttr<TargetClonesAttr>()) {
std::vector<std::string> Features;
StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex());
if (VersionStr.startswith("arch="))
TargetCPU = VersionStr.drop_front(sizeof("arch=") - 1);
else if (VersionStr != "default")
Features.push_back((StringRef{"+"} + VersionStr).str());
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
} else { } else {
FeatureMap = Target->getTargetOpts().FeatureMap; FeatureMap = Target->getTargetOpts().FeatureMap;
} }

View File

@ -1347,6 +1347,42 @@ IsStructurallyEquivalentLambdas(StructuralEquivalenceContext &Context,
return true; return true;
} }
/// Determine if context of a class is equivalent.
static bool IsRecordContextStructurallyEquivalent(RecordDecl *D1,
RecordDecl *D2) {
// The context should be completely equal, including anonymous and inline
// namespaces.
// We compare objects as part of full translation units, not subtrees of
// translation units.
DeclContext *DC1 = D1->getDeclContext()->getNonTransparentContext();
DeclContext *DC2 = D2->getDeclContext()->getNonTransparentContext();
while (true) {
// Special case: We allow a struct defined in a function to be equivalent
// with a similar struct defined outside of a function.
if ((DC1->isFunctionOrMethod() && DC2->isTranslationUnit()) ||
(DC2->isFunctionOrMethod() && DC1->isTranslationUnit()))
return true;
if (DC1->getDeclKind() != DC2->getDeclKind())
return false;
if (DC1->isTranslationUnit())
break;
if (DC1->isInlineNamespace() != DC2->isInlineNamespace())
return false;
if (const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
const auto *ND2 = cast<NamedDecl>(DC2);
if (!DC1->isInlineNamespace() &&
!IsStructurallyEquivalent(ND1->getIdentifier(), ND2->getIdentifier()))
return false;
}
DC1 = DC1->getParent()->getNonTransparentContext();
DC2 = DC2->getParent()->getNonTransparentContext();
}
return true;
}
/// Determine structural equivalence of two records. /// Determine structural equivalence of two records.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
RecordDecl *D1, RecordDecl *D2) { RecordDecl *D1, RecordDecl *D2) {
@ -1386,6 +1422,12 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
} }
} }
// If the records occur in different context (namespace), these should be
// different. This is specially important if the definition of one or both
// records is missing.
if (!IsRecordContextStructurallyEquivalent(D1, D2))
return false;
// If both declarations are class template specializations, we know // If both declarations are class template specializations, we know
// the ODR applies, so check the template and template arguments. // the ODR applies, so check the template and template arguments.
const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1); const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);

View File

@ -3256,6 +3256,8 @@ MultiVersionKind FunctionDecl::getMultiVersionKind() const {
return MultiVersionKind::CPUDispatch; return MultiVersionKind::CPUDispatch;
if (hasAttr<CPUSpecificAttr>()) if (hasAttr<CPUSpecificAttr>())
return MultiVersionKind::CPUSpecific; return MultiVersionKind::CPUSpecific;
if (hasAttr<TargetClonesAttr>())
return MultiVersionKind::TargetClones;
return MultiVersionKind::None; return MultiVersionKind::None;
} }
@ -3271,6 +3273,10 @@ bool FunctionDecl::isTargetMultiVersion() const {
return isMultiVersion() && hasAttr<TargetAttr>(); return isMultiVersion() && hasAttr<TargetAttr>();
} }
bool FunctionDecl::isTargetClonesMultiVersion() const {
return isMultiVersion() && hasAttr<TargetClonesAttr>();
}
void void
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
redeclarable_base::setPreviousDecl(PrevDecl); redeclarable_base::setPreviousDecl(PrevDecl);

View File

@ -964,7 +964,7 @@ SourceLocation Decl::getBodyRBrace() const {
return {}; return {};
} }
bool Decl::AccessDeclContextSanity() const { bool Decl::AccessDeclContextCheck() const {
#ifndef NDEBUG #ifndef NDEBUG
// Suppress this check if any of the following hold: // Suppress this check if any of the following hold:
// 1. this is the translation unit (and thus has no parent) // 1. this is the translation unit (and thus has no parent)
@ -1212,7 +1212,7 @@ bool DeclContext::Encloses(const DeclContext *DC) const {
return getPrimaryContext()->Encloses(DC); return getPrimaryContext()->Encloses(DC);
for (; DC; DC = DC->getParent()) for (; DC; DC = DC->getParent())
if (DC->getPrimaryContext() == this) if (!isa<LinkageSpecDecl>(DC) && DC->getPrimaryContext() == this)
return true; return true;
return false; return false;
} }

View File

@ -4681,6 +4681,7 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
return 2; return 2;
case AO__opencl_atomic_load: case AO__opencl_atomic_load:
case AO__hip_atomic_load:
case AO__c11_atomic_store: case AO__c11_atomic_store:
case AO__c11_atomic_exchange: case AO__c11_atomic_exchange:
case AO__atomic_load: case AO__atomic_load:
@ -4713,7 +4714,15 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
case AO__atomic_fetch_max: case AO__atomic_fetch_max:
return 3; return 3;
case AO__hip_atomic_exchange:
case AO__hip_atomic_fetch_add:
case AO__hip_atomic_fetch_and:
case AO__hip_atomic_fetch_or:
case AO__hip_atomic_fetch_xor:
case AO__hip_atomic_fetch_min:
case AO__hip_atomic_fetch_max:
case AO__opencl_atomic_store: case AO__opencl_atomic_store:
case AO__hip_atomic_store:
case AO__opencl_atomic_exchange: case AO__opencl_atomic_exchange:
case AO__opencl_atomic_fetch_add: case AO__opencl_atomic_fetch_add:
case AO__opencl_atomic_fetch_sub: case AO__opencl_atomic_fetch_sub:
@ -4728,9 +4737,10 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
case AO__c11_atomic_compare_exchange_strong: case AO__c11_atomic_compare_exchange_strong:
case AO__c11_atomic_compare_exchange_weak: case AO__c11_atomic_compare_exchange_weak:
return 5; return 5;
case AO__hip_atomic_compare_exchange_strong:
case AO__opencl_atomic_compare_exchange_strong: case AO__opencl_atomic_compare_exchange_strong:
case AO__opencl_atomic_compare_exchange_weak: case AO__opencl_atomic_compare_exchange_weak:
case AO__hip_atomic_compare_exchange_weak:
case AO__atomic_compare_exchange: case AO__atomic_compare_exchange:
case AO__atomic_compare_exchange_n: case AO__atomic_compare_exchange_n:
return 6; return 6;

View File

@ -7486,7 +7486,7 @@ class ExprEvaluatorBase
const Expr *Source = E->getSourceExpr(); const Expr *Source = E->getSourceExpr();
if (!Source) if (!Source)
return Error(E); return Error(E);
if (Source == E) { // sanity checking. if (Source == E) {
assert(0 && "OpaqueValueExpr recursively refers to itself"); assert(0 && "OpaqueValueExpr recursively refers to itself");
return Error(E); return Error(E);
} }

View File

@ -21,6 +21,7 @@
#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h" #include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h" #include "clang/AST/ExprCXX.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/Mangle.h" #include "clang/AST/Mangle.h"
#include "clang/AST/VTableBuilder.h" #include "clang/AST/VTableBuilder.h"
#include "clang/Basic/ABI.h" #include "clang/Basic/ABI.h"
@ -39,6 +40,18 @@ using namespace clang;
namespace { namespace {
// Get GlobalDecl of DeclContext of local entities.
static GlobalDecl getGlobalDeclAsDeclContext(const DeclContext *DC) {
GlobalDecl GD;
if (auto *CD = dyn_cast<CXXConstructorDecl>(DC))
GD = GlobalDecl(CD, Ctor_Complete);
else if (auto *DD = dyn_cast<CXXDestructorDecl>(DC))
GD = GlobalDecl(DD, Dtor_Complete);
else
GD = GlobalDecl(cast<FunctionDecl>(DC));
return GD;
}
struct msvc_hashing_ostream : public llvm::raw_svector_ostream { struct msvc_hashing_ostream : public llvm::raw_svector_ostream {
raw_ostream &OS; raw_ostream &OS;
llvm::SmallString<64> Buffer; llvm::SmallString<64> Buffer;
@ -345,9 +358,9 @@ class MicrosoftCXXNameMangler {
raw_ostream &getStream() const { return Out; } raw_ostream &getStream() const { return Out; }
void mangle(const NamedDecl *D, StringRef Prefix = "?"); void mangle(GlobalDecl GD, StringRef Prefix = "?");
void mangleName(const NamedDecl *ND); void mangleName(GlobalDecl GD);
void mangleFunctionEncoding(const FunctionDecl *FD, bool ShouldMangle); void mangleFunctionEncoding(GlobalDecl GD, bool ShouldMangle);
void mangleVariableEncoding(const VarDecl *VD); void mangleVariableEncoding(const VarDecl *VD);
void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD, void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD,
StringRef Prefix = "$"); StringRef Prefix = "$");
@ -370,7 +383,7 @@ class MicrosoftCXXNameMangler {
const FunctionDecl *D = nullptr, const FunctionDecl *D = nullptr,
bool ForceThisQuals = false, bool ForceThisQuals = false,
bool MangleExceptionSpec = true); bool MangleExceptionSpec = true);
void mangleNestedName(const NamedDecl *ND); void mangleNestedName(GlobalDecl GD);
private: private:
bool isStructorDecl(const NamedDecl *ND) const { bool isStructorDecl(const NamedDecl *ND) const {
@ -384,10 +397,10 @@ class MicrosoftCXXNameMangler {
AddrSpace == LangAS::ptr32_uptr)); AddrSpace == LangAS::ptr32_uptr));
} }
void mangleUnqualifiedName(const NamedDecl *ND) { void mangleUnqualifiedName(GlobalDecl GD) {
mangleUnqualifiedName(ND, ND->getDeclName()); mangleUnqualifiedName(GD, cast<NamedDecl>(GD.getDecl())->getDeclName());
} }
void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name); void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name);
void mangleSourceName(StringRef Name); void mangleSourceName(StringRef Name);
void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc); void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
void mangleCXXDtorType(CXXDtorType T); void mangleCXXDtorType(CXXDtorType T);
@ -396,9 +409,9 @@ class MicrosoftCXXNameMangler {
void manglePointerCVQualifiers(Qualifiers Quals); void manglePointerCVQualifiers(Qualifiers Quals);
void manglePointerExtQualifiers(Qualifiers Quals, QualType PointeeType); void manglePointerExtQualifiers(Qualifiers Quals, QualType PointeeType);
void mangleUnscopedTemplateName(const TemplateDecl *ND); void mangleUnscopedTemplateName(GlobalDecl GD);
void void
mangleTemplateInstantiationName(const TemplateDecl *TD, mangleTemplateInstantiationName(GlobalDecl GD,
const TemplateArgumentList &TemplateArgs); const TemplateArgumentList &TemplateArgs);
void mangleObjCMethodName(const ObjCMethodDecl *MD); void mangleObjCMethodName(const ObjCMethodDecl *MD);
@ -533,7 +546,8 @@ MicrosoftMangleContextImpl::shouldMangleStringLiteral(const StringLiteral *SL) {
return true; return true;
} }
void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { void MicrosoftCXXNameMangler::mangle(GlobalDecl GD, StringRef Prefix) {
const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
// MSVC doesn't mangle C++ names the same way it mangles extern "C" names. // MSVC doesn't mangle C++ names the same way it mangles extern "C" names.
// Therefore it's really important that we don't decorate the // Therefore it's really important that we don't decorate the
// name with leading underscores or leading/trailing at signs. So, by // name with leading underscores or leading/trailing at signs. So, by
@ -542,9 +556,9 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
// <mangled-name> ::= ? <name> <type-encoding> // <mangled-name> ::= ? <name> <type-encoding>
Out << Prefix; Out << Prefix;
mangleName(D); mangleName(GD);
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
mangleFunctionEncoding(FD, Context.shouldMangleDeclName(FD)); mangleFunctionEncoding(GD, Context.shouldMangleDeclName(FD));
else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
mangleVariableEncoding(VD); mangleVariableEncoding(VD);
else if (isa<MSGuidDecl>(D)) else if (isa<MSGuidDecl>(D))
@ -558,8 +572,9 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
llvm_unreachable("Tried to mangle unexpected NamedDecl!"); llvm_unreachable("Tried to mangle unexpected NamedDecl!");
} }
void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD, void MicrosoftCXXNameMangler::mangleFunctionEncoding(GlobalDecl GD,
bool ShouldMangle) { bool ShouldMangle) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
// <type-encoding> ::= <function-class> <function-type> // <type-encoding> ::= <function-class> <function-type>
// Since MSVC operates on the type as written and not the canonical type, it // Since MSVC operates on the type as written and not the canonical type, it
@ -770,13 +785,13 @@ void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk(
mangleCallingConvention(MD->getType()->castAs<FunctionProtoType>()); mangleCallingConvention(MD->getType()->castAs<FunctionProtoType>());
} }
void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) { void MicrosoftCXXNameMangler::mangleName(GlobalDecl GD) {
// <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @ // <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
// Always start with the unqualified name. // Always start with the unqualified name.
mangleUnqualifiedName(ND); mangleUnqualifiedName(GD);
mangleNestedName(ND); mangleNestedName(GD);
// Terminate the whole name with an '@'. // Terminate the whole name with an '@'.
Out << '@'; Out << '@';
@ -844,13 +859,14 @@ void MicrosoftCXXNameMangler::mangleBits(llvm::APInt Value) {
} }
} }
static const TemplateDecl * static GlobalDecl isTemplate(GlobalDecl GD,
isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { const TemplateArgumentList *&TemplateArgs) {
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
// Check if we have a function template. // Check if we have a function template.
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
if (const TemplateDecl *TD = FD->getPrimaryTemplate()) { if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
TemplateArgs = FD->getTemplateSpecializationArgs(); TemplateArgs = FD->getTemplateSpecializationArgs();
return TD; return GD.getWithDecl(TD);
} }
} }
@ -858,21 +874,22 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
if (const ClassTemplateSpecializationDecl *Spec = if (const ClassTemplateSpecializationDecl *Spec =
dyn_cast<ClassTemplateSpecializationDecl>(ND)) { dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
TemplateArgs = &Spec->getTemplateArgs(); TemplateArgs = &Spec->getTemplateArgs();
return Spec->getSpecializedTemplate(); return GD.getWithDecl(Spec->getSpecializedTemplate());
} }
// Check if we have a variable template. // Check if we have a variable template.
if (const VarTemplateSpecializationDecl *Spec = if (const VarTemplateSpecializationDecl *Spec =
dyn_cast<VarTemplateSpecializationDecl>(ND)) { dyn_cast<VarTemplateSpecializationDecl>(ND)) {
TemplateArgs = &Spec->getTemplateArgs(); TemplateArgs = &Spec->getTemplateArgs();
return Spec->getSpecializedTemplate(); return GD.getWithDecl(Spec->getSpecializedTemplate());
} }
return nullptr; return GlobalDecl();
} }
void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, void MicrosoftCXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
DeclarationName Name) { DeclarationName Name) {
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
// <unqualified-name> ::= <operator-name> // <unqualified-name> ::= <operator-name>
// ::= <ctor-dtor-name> // ::= <ctor-dtor-name>
// ::= <source-name> // ::= <source-name>
@ -880,11 +897,11 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// Check if we have a template. // Check if we have a template.
const TemplateArgumentList *TemplateArgs = nullptr; const TemplateArgumentList *TemplateArgs = nullptr;
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) {
// Function templates aren't considered for name back referencing. This // Function templates aren't considered for name back referencing. This
// makes sense since function templates aren't likely to occur multiple // makes sense since function templates aren't likely to occur multiple
// times in a symbol. // times in a symbol.
if (isa<FunctionTemplateDecl>(TD)) { if (isa<FunctionTemplateDecl>(TD.getDecl())) {
mangleTemplateInstantiationName(TD, *TemplateArgs); mangleTemplateInstantiationName(TD, *TemplateArgs);
Out << '@'; Out << '@';
return; return;
@ -945,7 +962,19 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
switch (Name.getNameKind()) { switch (Name.getNameKind()) {
case DeclarationName::Identifier: { case DeclarationName::Identifier: {
if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) { if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
mangleSourceName(II->getName()); bool IsDeviceStub =
ND &&
((isa<FunctionDecl>(ND) && ND->hasAttr<CUDAGlobalAttr>()) ||
(isa<FunctionTemplateDecl>(ND) &&
cast<FunctionTemplateDecl>(ND)
->getTemplatedDecl()
->hasAttr<CUDAGlobalAttr>())) &&
GD.getKernelReferenceKind() == KernelReferenceKind::Stub;
if (IsDeviceStub)
mangleSourceName(
(llvm::Twine("__device_stub__") + II->getName()).str());
else
mangleSourceName(II->getName());
break; break;
} }
@ -1146,7 +1175,8 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// <postfix> ::= <unqualified-name> [<postfix>] // <postfix> ::= <unqualified-name> [<postfix>]
// ::= <substitution> [<postfix>] // ::= <substitution> [<postfix>]
void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { void MicrosoftCXXNameMangler::mangleNestedName(GlobalDecl GD) {
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
const DeclContext *DC = getEffectiveDeclContext(ND); const DeclContext *DC = getEffectiveDeclContext(ND);
while (!DC->isTranslationUnit()) { while (!DC->isTranslationUnit()) {
if (isa<TagDecl>(ND) || isa<VarDecl>(ND)) { if (isa<TagDecl>(ND) || isa<VarDecl>(ND)) {
@ -1229,7 +1259,7 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
} else if (isa<NamedDecl>(DC)) { } else if (isa<NamedDecl>(DC)) {
ND = cast<NamedDecl>(DC); ND = cast<NamedDecl>(DC);
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
mangle(FD, "?"); mangle(getGlobalDeclAsDeclContext(FD), "?");
break; break;
} else { } else {
mangleUnqualifiedName(ND); mangleUnqualifiedName(ND);
@ -1418,7 +1448,7 @@ void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
} }
void MicrosoftCXXNameMangler::mangleTemplateInstantiationName( void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(
const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs) { GlobalDecl GD, const TemplateArgumentList &TemplateArgs) {
// <template-name> ::= <unscoped-template-name> <template-args> // <template-name> ::= <unscoped-template-name> <template-args>
// ::= <substitution> // ::= <substitution>
// Always start with the unqualified name. // Always start with the unqualified name.
@ -1433,8 +1463,8 @@ void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(
TemplateArgBackReferences.swap(OuterTemplateArgsContext); TemplateArgBackReferences.swap(OuterTemplateArgsContext);
PassObjectSizeArgs.swap(OuterPassObjectSizeArgs); PassObjectSizeArgs.swap(OuterPassObjectSizeArgs);
mangleUnscopedTemplateName(TD); mangleUnscopedTemplateName(GD);
mangleTemplateArgs(TD, TemplateArgs); mangleTemplateArgs(cast<TemplateDecl>(GD.getDecl()), TemplateArgs);
// Restore the previous back reference contexts. // Restore the previous back reference contexts.
NameBackReferences.swap(OuterTemplateContext); NameBackReferences.swap(OuterTemplateContext);
@ -1443,11 +1473,10 @@ void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(
PassObjectSizeArgs.swap(OuterPassObjectSizeArgs); PassObjectSizeArgs.swap(OuterPassObjectSizeArgs);
} }
void void MicrosoftCXXNameMangler::mangleUnscopedTemplateName(GlobalDecl GD) {
MicrosoftCXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *TD) {
// <unscoped-template-name> ::= ?$ <unqualified-name> // <unscoped-template-name> ::= ?$ <unqualified-name>
Out << "?$"; Out << "?$";
mangleUnqualifiedName(TD); mangleUnqualifiedName(GD);
} }
void MicrosoftCXXNameMangler::mangleIntegerLiteral( void MicrosoftCXXNameMangler::mangleIntegerLiteral(
@ -3323,17 +3352,17 @@ void MicrosoftMangleContextImpl::mangleCXXName(GlobalDecl GD,
if (auto *CD = dyn_cast<CXXConstructorDecl>(D)) { if (auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
auto Type = GD.getCtorType(); auto Type = GD.getCtorType();
MicrosoftCXXNameMangler mangler(*this, MHO, CD, Type); MicrosoftCXXNameMangler mangler(*this, MHO, CD, Type);
return mangler.mangle(D); return mangler.mangle(GD);
} }
if (auto *DD = dyn_cast<CXXDestructorDecl>(D)) { if (auto *DD = dyn_cast<CXXDestructorDecl>(D)) {
auto Type = GD.getDtorType(); auto Type = GD.getDtorType();
MicrosoftCXXNameMangler mangler(*this, MHO, DD, Type); MicrosoftCXXNameMangler mangler(*this, MHO, DD, Type);
return mangler.mangle(D); return mangler.mangle(GD);
} }
MicrosoftCXXNameMangler Mangler(*this, MHO); MicrosoftCXXNameMangler Mangler(*this, MHO);
return Mangler.mangle(D); return Mangler.mangle(GD);
} }
void MicrosoftCXXNameMangler::mangleType(const ExtIntType *T, Qualifiers, void MicrosoftCXXNameMangler::mangleType(const ExtIntType *T, Qualifiers,

View File

@ -1691,7 +1691,8 @@ void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) {
PrintExpr(Node->getPtr()); PrintExpr(Node->getPtr());
if (Node->getOp() != AtomicExpr::AO__c11_atomic_load && if (Node->getOp() != AtomicExpr::AO__c11_atomic_load &&
Node->getOp() != AtomicExpr::AO__atomic_load_n && Node->getOp() != AtomicExpr::AO__atomic_load_n &&
Node->getOp() != AtomicExpr::AO__opencl_atomic_load) { Node->getOp() != AtomicExpr::AO__opencl_atomic_load &&
Node->getOp() != AtomicExpr::AO__hip_atomic_load) {
OS << ", "; OS << ", ";
PrintExpr(Node->getVal1()); PrintExpr(Node->getVal1());
} }

View File

@ -0,0 +1,35 @@
//===- TypeErasedDataflowAnalysis.cpp -------------------------------------===//
//
// 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 type-erased base types and functions for building dataflow
// analyses that run over Control-Flow Graphs (CFGs).
//
//===----------------------------------------------------------------------===//
#include <vector>
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
#include "llvm/ADT/Optional.h"
using namespace clang;
using namespace dataflow;
std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>>
runTypeErasedDataflowAnalysis(const CFG &Cfg,
TypeErasedDataflowAnalysis &Analysis,
const Environment &InitEnv) {
// FIXME: Consider enforcing that `Cfg` meets the requirements that
// are specified in the header. This could be done by remembering
// what options were used to build `Cfg` and asserting on them here.
// FIXME: Implement work list-based algorithm to compute the fixed
// point of `Analysis::transform` for every basic block in `Cfg`.
return {};
}

View File

@ -140,8 +140,8 @@ bool AArch64TargetInfo::setABI(const std::string &Name) {
bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, bool AArch64TargetInfo::validateBranchProtection(StringRef Spec,
BranchProtectionInfo &BPI, BranchProtectionInfo &BPI,
StringRef &Err) const { StringRef &Err) const {
llvm::AArch64::ParsedBranchProtection PBP; llvm::ARM::ParsedBranchProtection PBP;
if (!llvm::AArch64::parseBranchProtection(Spec, PBP, Err)) if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err))
return false; return false;
BPI.SignReturnAddr = BPI.SignReturnAddr =

View File

@ -367,6 +367,28 @@ bool ARMTargetInfo::setABI(const std::string &Name) {
return false; return false;
} }
bool ARMTargetInfo::validateBranchProtection(StringRef Spec,
BranchProtectionInfo &BPI,
StringRef &Err) const {
llvm::ARM::ParsedBranchProtection PBP;
if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err))
return false;
BPI.SignReturnAddr =
llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)
.Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf)
.Case("all", LangOptions::SignReturnAddressScopeKind::All)
.Default(LangOptions::SignReturnAddressScopeKind::None);
// Don't care for the sign key, beyond issuing a warning.
if (PBP.Key == "b_key")
Err = "b-key";
BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey;
BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement;
return true;
}
// FIXME: This should be based on Arch attributes, not CPU names. // FIXME: This should be based on Arch attributes, not CPU names.
bool ARMTargetInfo::initFeatureMap( bool ARMTargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
@ -874,6 +896,16 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__ARM_BF16_FORMAT_ALTERNATIVE", "1"); Builder.defineMacro("__ARM_BF16_FORMAT_ALTERNATIVE", "1");
} }
if (Opts.BranchTargetEnforcement)
Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1");
if (Opts.hasSignReturnAddress()) {
unsigned Value = Opts.isSignReturnAddressWithAKey() ? 1 : 2;
if (Opts.isSignReturnAddressScopeAll())
Value |= 1 << 2;
Builder.defineMacro("__ARM_FEATURE_PAC_DEFAULT", Twine(Value));
}
switch (ArchKind) { switch (ArchKind) {
default: default:
break; break;

View File

@ -123,6 +123,9 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo {
StringRef getABI() const override; StringRef getABI() const override;
bool setABI(const std::string &Name) override; bool setABI(const std::string &Name) override;
bool validateBranchProtection(StringRef, BranchProtectionInfo &,
StringRef &) const override;
// FIXME: This should be based on Arch attributes, not CPU names. // FIXME: This should be based on Arch attributes, not CPU names.
bool bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,

View File

@ -181,8 +181,10 @@ static void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) {
Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1)); Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1));
if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) { if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) {
if (Opts.CPlusPlus20) if (Opts.CPlusPlus2b)
Builder.defineMacro("_MSVC_LANG", "201705L"); Builder.defineMacro("_MSVC_LANG", "202004L");
else if (Opts.CPlusPlus20)
Builder.defineMacro("_MSVC_LANG", "202002L");
else if (Opts.CPlusPlus17) else if (Opts.CPlusPlus17)
Builder.defineMacro("_MSVC_LANG", "201703L"); Builder.defineMacro("_MSVC_LANG", "201703L");
else if (Opts.CPlusPlus14) else if (Opts.CPlusPlus14)
@ -201,6 +203,14 @@ static void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) {
} }
Builder.defineMacro("_INTEGRAL_MAX_BITS", "64"); Builder.defineMacro("_INTEGRAL_MAX_BITS", "64");
// Starting with VS 2022 17.1, MSVC predefines the below macro to inform
// users of the execution character set defined at compile time.
// The value given is the Windows Code Page Identifier:
// https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers
//
// Clang currently only supports UTF-8, so we'll use 65001
Builder.defineMacro("_MSVC_EXECUTION_CHARACTER_SET", "65001");
} }
void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts, void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts,

View File

@ -56,9 +56,14 @@ static const unsigned SPIRDefIsGenMap[] = {
0, // opencl_generic 0, // opencl_generic
0, // opencl_global_device 0, // opencl_global_device
0, // opencl_global_host 0, // opencl_global_host
0, // cuda_device // cuda_* address space mapping is intended for HIPSPV (HIP to SPIR-V
0, // cuda_constant // translation). This mapping is enabled when the language mode is HIP.
0, // cuda_shared 1, // cuda_device
// cuda_constant pointer can be casted to default/"flat" pointer, but in
// SPIR-V casts between constant and generic pointers are not allowed. For
// this reason cuda_constant is mapped to SPIR-V CrossWorkgroup.
1, // cuda_constant
3, // cuda_shared
1, // sycl_global 1, // sycl_global
5, // sycl_global_device 5, // sycl_global_device
6, // sycl_global_host 6, // sycl_global_host
@ -74,6 +79,8 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo {
protected: protected:
BaseSPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &) BaseSPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) { : TargetInfo(Triple) {
assert((Triple.isSPIR() || Triple.isSPIRV()) &&
"Invalid architecture for SPIR or SPIR-V.");
assert(getTriple().getOS() == llvm::Triple::UnknownOS && assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
"SPIR(-V) target must use unknown OS"); "SPIR(-V) target must use unknown OS");
assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
@ -137,11 +144,16 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo {
// FIXME: SYCL specification considers unannotated pointers and references // FIXME: SYCL specification considers unannotated pointers and references
// to be pointing to the generic address space. See section 5.9.3 of // to be pointing to the generic address space. See section 5.9.3 of
// SYCL 2020 specification. // SYCL 2020 specification.
// Currently, there is no way of representing SYCL's default address space // Currently, there is no way of representing SYCL's and HIP's default
// language semantic along with the semantics of embedded C's default // address space language semantic along with the semantics of embedded C's
// address space in the same address space map. Hence the map needs to be // default address space in the same address space map. Hence the map needs
// reset to allow mapping to the desired value of 'Default' entry for SYCL. // to be reset to allow mapping to the desired value of 'Default' entry for
setAddressSpaceMap(/*DefaultIsGeneric=*/Opts.SYCLIsDevice); // SYCL and HIP.
setAddressSpaceMap(
/*DefaultIsGeneric=*/Opts.SYCLIsDevice ||
// The address mapping from HIP language for device code is only defined
// for SPIR-V.
(getTriple().isSPIRV() && Opts.HIP && Opts.CUDAIsDevice));
} }
void setSupportedOpenCLOpts() override { void setSupportedOpenCLOpts() override {
@ -159,6 +171,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public BaseSPIRTargetInfo {
public: public:
SPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) SPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: BaseSPIRTargetInfo(Triple, Opts) { : BaseSPIRTargetInfo(Triple, Opts) {
assert(Triple.isSPIR() && "Invalid architecture for SPIR.");
assert(getTriple().getOS() == llvm::Triple::UnknownOS && assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
"SPIR target must use unknown OS"); "SPIR target must use unknown OS");
assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
@ -177,6 +190,8 @@ class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo {
public: public:
SPIR32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) SPIR32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: SPIRTargetInfo(Triple, Opts) { : SPIRTargetInfo(Triple, Opts) {
assert(Triple.getArch() == llvm::Triple::spir &&
"Invalid architecture for 32-bit SPIR.");
PointerWidth = PointerAlign = 32; PointerWidth = PointerAlign = 32;
SizeType = TargetInfo::UnsignedInt; SizeType = TargetInfo::UnsignedInt;
PtrDiffType = IntPtrType = TargetInfo::SignedInt; PtrDiffType = IntPtrType = TargetInfo::SignedInt;
@ -192,6 +207,8 @@ class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo {
public: public:
SPIR64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) SPIR64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: SPIRTargetInfo(Triple, Opts) { : SPIRTargetInfo(Triple, Opts) {
assert(Triple.getArch() == llvm::Triple::spir64 &&
"Invalid architecture for 64-bit SPIR.");
PointerWidth = PointerAlign = 64; PointerWidth = PointerAlign = 64;
SizeType = TargetInfo::UnsignedLong; SizeType = TargetInfo::UnsignedLong;
PtrDiffType = IntPtrType = TargetInfo::SignedLong; PtrDiffType = IntPtrType = TargetInfo::SignedLong;
@ -207,6 +224,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRTargetInfo {
public: public:
SPIRVTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) SPIRVTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: BaseSPIRTargetInfo(Triple, Opts) { : BaseSPIRTargetInfo(Triple, Opts) {
assert(Triple.isSPIRV() && "Invalid architecture for SPIR-V.");
assert(getTriple().getOS() == llvm::Triple::UnknownOS && assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
"SPIR-V target must use unknown OS"); "SPIR-V target must use unknown OS");
assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
@ -225,6 +243,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public SPIRVTargetInfo {
public: public:
SPIRV32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) SPIRV32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: SPIRVTargetInfo(Triple, Opts) { : SPIRVTargetInfo(Triple, Opts) {
assert(Triple.getArch() == llvm::Triple::spirv32 &&
"Invalid architecture for 32-bit SPIR-V.");
PointerWidth = PointerAlign = 32; PointerWidth = PointerAlign = 32;
SizeType = TargetInfo::UnsignedInt; SizeType = TargetInfo::UnsignedInt;
PtrDiffType = IntPtrType = TargetInfo::SignedInt; PtrDiffType = IntPtrType = TargetInfo::SignedInt;
@ -240,6 +260,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public SPIRVTargetInfo {
public: public:
SPIRV64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) SPIRV64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: SPIRVTargetInfo(Triple, Opts) { : SPIRVTargetInfo(Triple, Opts) {
assert(Triple.getArch() == llvm::Triple::spirv64 &&
"Invalid architecture for 64-bit SPIR-V.");
PointerWidth = PointerAlign = 64; PointerWidth = PointerAlign = 64;
SizeType = TargetInfo::UnsignedLong; SizeType = TargetInfo::UnsignedLong;
PtrDiffType = IntPtrType = TargetInfo::SignedLong; PtrDiffType = IntPtrType = TargetInfo::SignedLong;

View File

@ -239,9 +239,9 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasAVX512ER = true; HasAVX512ER = true;
} else if (Feature == "+avx512fp16") { } else if (Feature == "+avx512fp16") {
HasAVX512FP16 = true; HasAVX512FP16 = true;
HasFloat16 = true;
} else if (Feature == "+avx512pf") { } else if (Feature == "+avx512pf") {
HasAVX512PF = true; HasAVX512PF = true;
HasLegalHalfType = true;
} else if (Feature == "+avx512dq") { } else if (Feature == "+avx512dq") {
HasAVX512DQ = true; HasAVX512DQ = true;
} else if (Feature == "+avx512bitalg") { } else if (Feature == "+avx512bitalg") {
@ -369,8 +369,6 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
.Default(NoXOP); .Default(NoXOP);
XOPLevel = std::max(XOPLevel, XLevel); XOPLevel = std::max(XOPLevel, XLevel);
} }
// Turn on _float16 for x86 (feature sse2)
HasFloat16 = SSELevel >= SSE2;
// LLVM doesn't have a separate switch for fpmath, so only accept it if it // LLVM doesn't have a separate switch for fpmath, so only accept it if it
// matches the selected sse level. // matches the selected sse level.
@ -384,12 +382,10 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
SimdDefaultAlign = SimdDefaultAlign =
hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128; hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
if (!HasX87) { // FIXME: We should allow long double type on 32-bits to match with GCC.
if (LongDoubleFormat == &llvm::APFloat::x87DoubleExtended()) // This requires backend to be able to lower f80 without x87 first.
HasLongDouble = false; if (!HasX87 && LongDoubleFormat == &llvm::APFloat::x87DoubleExtended())
if (getTriple().getArch() == llvm::Triple::x86) HasLongDouble = false;
HasFPReturn = false;
}
return true; return true;
} }

View File

@ -1034,8 +1034,9 @@ void EmitAssemblyHelper::EmitAssemblyWithLegacyPassManager(
if (!ThinLinkOS) if (!ThinLinkOS)
return; return;
} }
TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
CodeGenOpts.EnableSplitLTOUnit); TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
CodeGenOpts.EnableSplitLTOUnit);
PerModulePasses.add(createWriteThinLTOBitcodePass( PerModulePasses.add(createWriteThinLTOBitcodePass(
*OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr)); *OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr));
} else { } else {
@ -1049,8 +1050,9 @@ void EmitAssemblyHelper::EmitAssemblyWithLegacyPassManager(
if (EmitLTOSummary) { if (EmitLTOSummary) {
if (!TheModule->getModuleFlag("ThinLTO")) if (!TheModule->getModuleFlag("ThinLTO"))
TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
uint32_t(1)); TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
uint32_t(1));
} }
PerModulePasses.add(createBitcodeWriterPass( PerModulePasses.add(createBitcodeWriterPass(
@ -1451,8 +1453,9 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
if (!ThinLinkOS) if (!ThinLinkOS)
return; return;
} }
TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
CodeGenOpts.EnableSplitLTOUnit); TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
CodeGenOpts.EnableSplitLTOUnit);
MPM.addPass(ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &ThinLinkOS->os() MPM.addPass(ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &ThinLinkOS->os()
: nullptr)); : nullptr));
} else { } else {
@ -1465,8 +1468,9 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
if (EmitLTOSummary) { if (EmitLTOSummary) {
if (!TheModule->getModuleFlag("ThinLTO")) if (!TheModule->getModuleFlag("ThinLTO"))
TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
uint32_t(1)); TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
uint32_t(1));
} }
MPM.addPass( MPM.addPass(
BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, EmitLTOSummary)); BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, EmitLTOSummary));

View File

@ -524,12 +524,14 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
llvm_unreachable("Already handled!"); llvm_unreachable("Already handled!");
case AtomicExpr::AO__c11_atomic_compare_exchange_strong: case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2, emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2,
FailureOrder, Size, Order, Scope); FailureOrder, Size, Order, Scope);
return; return;
case AtomicExpr::AO__c11_atomic_compare_exchange_weak: case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2, emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2,
FailureOrder, Size, Order, Scope); FailureOrder, Size, Order, Scope);
return; return;
@ -565,6 +567,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
} }
case AtomicExpr::AO__c11_atomic_load: case AtomicExpr::AO__c11_atomic_load:
case AtomicExpr::AO__opencl_atomic_load: case AtomicExpr::AO__opencl_atomic_load:
case AtomicExpr::AO__hip_atomic_load:
case AtomicExpr::AO__atomic_load_n: case AtomicExpr::AO__atomic_load_n:
case AtomicExpr::AO__atomic_load: { case AtomicExpr::AO__atomic_load: {
llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr); llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr);
@ -576,6 +579,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
case AtomicExpr::AO__c11_atomic_store: case AtomicExpr::AO__c11_atomic_store:
case AtomicExpr::AO__opencl_atomic_store: case AtomicExpr::AO__opencl_atomic_store:
case AtomicExpr::AO__hip_atomic_store:
case AtomicExpr::AO__atomic_store: case AtomicExpr::AO__atomic_store:
case AtomicExpr::AO__atomic_store_n: { case AtomicExpr::AO__atomic_store_n: {
llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1); llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);
@ -586,6 +590,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
} }
case AtomicExpr::AO__c11_atomic_exchange: case AtomicExpr::AO__c11_atomic_exchange:
case AtomicExpr::AO__hip_atomic_exchange:
case AtomicExpr::AO__opencl_atomic_exchange: case AtomicExpr::AO__opencl_atomic_exchange:
case AtomicExpr::AO__atomic_exchange_n: case AtomicExpr::AO__atomic_exchange_n:
case AtomicExpr::AO__atomic_exchange: case AtomicExpr::AO__atomic_exchange:
@ -597,6 +602,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
: llvm::Instruction::Add; : llvm::Instruction::Add;
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_add: case AtomicExpr::AO__c11_atomic_fetch_add:
case AtomicExpr::AO__hip_atomic_fetch_add:
case AtomicExpr::AO__opencl_atomic_fetch_add: case AtomicExpr::AO__opencl_atomic_fetch_add:
case AtomicExpr::AO__atomic_fetch_add: case AtomicExpr::AO__atomic_fetch_add:
Op = E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FAdd Op = E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FAdd
@ -618,6 +624,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
PostOpMinMax = true; PostOpMinMax = true;
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_min: case AtomicExpr::AO__c11_atomic_fetch_min:
case AtomicExpr::AO__hip_atomic_fetch_min:
case AtomicExpr::AO__opencl_atomic_fetch_min: case AtomicExpr::AO__opencl_atomic_fetch_min:
case AtomicExpr::AO__atomic_fetch_min: case AtomicExpr::AO__atomic_fetch_min:
Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Min Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Min
@ -628,6 +635,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
PostOpMinMax = true; PostOpMinMax = true;
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_max: case AtomicExpr::AO__c11_atomic_fetch_max:
case AtomicExpr::AO__hip_atomic_fetch_max:
case AtomicExpr::AO__opencl_atomic_fetch_max: case AtomicExpr::AO__opencl_atomic_fetch_max:
case AtomicExpr::AO__atomic_fetch_max: case AtomicExpr::AO__atomic_fetch_max:
Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Max Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Max
@ -638,6 +646,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
PostOp = llvm::Instruction::And; PostOp = llvm::Instruction::And;
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_and: case AtomicExpr::AO__c11_atomic_fetch_and:
case AtomicExpr::AO__hip_atomic_fetch_and:
case AtomicExpr::AO__opencl_atomic_fetch_and: case AtomicExpr::AO__opencl_atomic_fetch_and:
case AtomicExpr::AO__atomic_fetch_and: case AtomicExpr::AO__atomic_fetch_and:
Op = llvm::AtomicRMWInst::And; Op = llvm::AtomicRMWInst::And;
@ -647,6 +656,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
PostOp = llvm::Instruction::Or; PostOp = llvm::Instruction::Or;
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_or: case AtomicExpr::AO__c11_atomic_fetch_or:
case AtomicExpr::AO__hip_atomic_fetch_or:
case AtomicExpr::AO__opencl_atomic_fetch_or: case AtomicExpr::AO__opencl_atomic_fetch_or:
case AtomicExpr::AO__atomic_fetch_or: case AtomicExpr::AO__atomic_fetch_or:
Op = llvm::AtomicRMWInst::Or; Op = llvm::AtomicRMWInst::Or;
@ -656,6 +666,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
PostOp = llvm::Instruction::Xor; PostOp = llvm::Instruction::Xor;
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_xor: case AtomicExpr::AO__c11_atomic_fetch_xor:
case AtomicExpr::AO__hip_atomic_fetch_xor:
case AtomicExpr::AO__opencl_atomic_fetch_xor: case AtomicExpr::AO__opencl_atomic_fetch_xor:
case AtomicExpr::AO__atomic_fetch_xor: case AtomicExpr::AO__atomic_fetch_xor:
Op = llvm::AtomicRMWInst::Xor; Op = llvm::AtomicRMWInst::Xor;
@ -838,6 +849,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__c11_atomic_load: case AtomicExpr::AO__c11_atomic_load:
case AtomicExpr::AO__opencl_atomic_load: case AtomicExpr::AO__opencl_atomic_load:
case AtomicExpr::AO__hip_atomic_load:
case AtomicExpr::AO__atomic_load_n: case AtomicExpr::AO__atomic_load_n:
break; break;
@ -857,7 +869,9 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__c11_atomic_compare_exchange_strong: case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
case AtomicExpr::AO__c11_atomic_compare_exchange_weak: case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
case AtomicExpr::AO__atomic_compare_exchange_n: case AtomicExpr::AO__atomic_compare_exchange_n:
case AtomicExpr::AO__atomic_compare_exchange: case AtomicExpr::AO__atomic_compare_exchange:
Val1 = EmitPointerWithAlignment(E->getVal1()); Val1 = EmitPointerWithAlignment(E->getVal1());
@ -873,6 +887,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__c11_atomic_fetch_add: case AtomicExpr::AO__c11_atomic_fetch_add:
case AtomicExpr::AO__c11_atomic_fetch_sub: case AtomicExpr::AO__c11_atomic_fetch_sub:
case AtomicExpr::AO__hip_atomic_fetch_add:
case AtomicExpr::AO__opencl_atomic_fetch_add: case AtomicExpr::AO__opencl_atomic_fetch_add:
case AtomicExpr::AO__opencl_atomic_fetch_sub: case AtomicExpr::AO__opencl_atomic_fetch_sub:
if (MemTy->isPointerType()) { if (MemTy->isPointerType()) {
@ -901,7 +916,9 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__c11_atomic_store: case AtomicExpr::AO__c11_atomic_store:
case AtomicExpr::AO__c11_atomic_exchange: case AtomicExpr::AO__c11_atomic_exchange:
case AtomicExpr::AO__opencl_atomic_store: case AtomicExpr::AO__opencl_atomic_store:
case AtomicExpr::AO__hip_atomic_store:
case AtomicExpr::AO__opencl_atomic_exchange: case AtomicExpr::AO__opencl_atomic_exchange:
case AtomicExpr::AO__hip_atomic_exchange:
case AtomicExpr::AO__atomic_store_n: case AtomicExpr::AO__atomic_store_n:
case AtomicExpr::AO__atomic_exchange_n: case AtomicExpr::AO__atomic_exchange_n:
case AtomicExpr::AO__c11_atomic_fetch_and: case AtomicExpr::AO__c11_atomic_fetch_and:
@ -916,8 +933,11 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__opencl_atomic_fetch_min: case AtomicExpr::AO__opencl_atomic_fetch_min:
case AtomicExpr::AO__opencl_atomic_fetch_max: case AtomicExpr::AO__opencl_atomic_fetch_max:
case AtomicExpr::AO__atomic_fetch_and: case AtomicExpr::AO__atomic_fetch_and:
case AtomicExpr::AO__hip_atomic_fetch_and:
case AtomicExpr::AO__atomic_fetch_or: case AtomicExpr::AO__atomic_fetch_or:
case AtomicExpr::AO__hip_atomic_fetch_or:
case AtomicExpr::AO__atomic_fetch_xor: case AtomicExpr::AO__atomic_fetch_xor:
case AtomicExpr::AO__hip_atomic_fetch_xor:
case AtomicExpr::AO__atomic_fetch_nand: case AtomicExpr::AO__atomic_fetch_nand:
case AtomicExpr::AO__atomic_and_fetch: case AtomicExpr::AO__atomic_and_fetch:
case AtomicExpr::AO__atomic_or_fetch: case AtomicExpr::AO__atomic_or_fetch:
@ -926,7 +946,9 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__atomic_max_fetch: case AtomicExpr::AO__atomic_max_fetch:
case AtomicExpr::AO__atomic_min_fetch: case AtomicExpr::AO__atomic_min_fetch:
case AtomicExpr::AO__atomic_fetch_max: case AtomicExpr::AO__atomic_fetch_max:
case AtomicExpr::AO__hip_atomic_fetch_max:
case AtomicExpr::AO__atomic_fetch_min: case AtomicExpr::AO__atomic_fetch_min:
case AtomicExpr::AO__hip_atomic_fetch_min:
Val1 = EmitValToTemp(*this, E->getVal1()); Val1 = EmitValToTemp(*this, E->getVal1());
break; break;
} }
@ -968,11 +990,14 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__c11_atomic_fetch_add: case AtomicExpr::AO__c11_atomic_fetch_add:
case AtomicExpr::AO__opencl_atomic_fetch_add: case AtomicExpr::AO__opencl_atomic_fetch_add:
case AtomicExpr::AO__atomic_fetch_add: case AtomicExpr::AO__atomic_fetch_add:
case AtomicExpr::AO__hip_atomic_fetch_add:
case AtomicExpr::AO__c11_atomic_fetch_and: case AtomicExpr::AO__c11_atomic_fetch_and:
case AtomicExpr::AO__opencl_atomic_fetch_and: case AtomicExpr::AO__opencl_atomic_fetch_and:
case AtomicExpr::AO__hip_atomic_fetch_and:
case AtomicExpr::AO__atomic_fetch_and: case AtomicExpr::AO__atomic_fetch_and:
case AtomicExpr::AO__c11_atomic_fetch_or: case AtomicExpr::AO__c11_atomic_fetch_or:
case AtomicExpr::AO__opencl_atomic_fetch_or: case AtomicExpr::AO__opencl_atomic_fetch_or:
case AtomicExpr::AO__hip_atomic_fetch_or:
case AtomicExpr::AO__atomic_fetch_or: case AtomicExpr::AO__atomic_fetch_or:
case AtomicExpr::AO__c11_atomic_fetch_nand: case AtomicExpr::AO__c11_atomic_fetch_nand:
case AtomicExpr::AO__atomic_fetch_nand: case AtomicExpr::AO__atomic_fetch_nand:
@ -984,6 +1009,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__opencl_atomic_fetch_min: case AtomicExpr::AO__opencl_atomic_fetch_min:
case AtomicExpr::AO__opencl_atomic_fetch_max: case AtomicExpr::AO__opencl_atomic_fetch_max:
case AtomicExpr::AO__atomic_fetch_xor: case AtomicExpr::AO__atomic_fetch_xor:
case AtomicExpr::AO__hip_atomic_fetch_xor:
case AtomicExpr::AO__c11_atomic_fetch_max: case AtomicExpr::AO__c11_atomic_fetch_max:
case AtomicExpr::AO__c11_atomic_fetch_min: case AtomicExpr::AO__c11_atomic_fetch_min:
case AtomicExpr::AO__atomic_add_fetch: case AtomicExpr::AO__atomic_add_fetch:
@ -993,7 +1019,9 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__atomic_sub_fetch: case AtomicExpr::AO__atomic_sub_fetch:
case AtomicExpr::AO__atomic_xor_fetch: case AtomicExpr::AO__atomic_xor_fetch:
case AtomicExpr::AO__atomic_fetch_max: case AtomicExpr::AO__atomic_fetch_max:
case AtomicExpr::AO__hip_atomic_fetch_max:
case AtomicExpr::AO__atomic_fetch_min: case AtomicExpr::AO__atomic_fetch_min:
case AtomicExpr::AO__hip_atomic_fetch_min:
case AtomicExpr::AO__atomic_max_fetch: case AtomicExpr::AO__atomic_max_fetch:
case AtomicExpr::AO__atomic_min_fetch: case AtomicExpr::AO__atomic_min_fetch:
// For these, only library calls for certain sizes exist. // For these, only library calls for certain sizes exist.
@ -1014,10 +1042,15 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__c11_atomic_exchange: case AtomicExpr::AO__c11_atomic_exchange:
case AtomicExpr::AO__c11_atomic_compare_exchange_weak: case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
case AtomicExpr::AO__c11_atomic_compare_exchange_strong: case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
case AtomicExpr::AO__opencl_atomic_load: case AtomicExpr::AO__opencl_atomic_load:
case AtomicExpr::AO__hip_atomic_load:
case AtomicExpr::AO__opencl_atomic_store: case AtomicExpr::AO__opencl_atomic_store:
case AtomicExpr::AO__hip_atomic_store:
case AtomicExpr::AO__opencl_atomic_exchange: case AtomicExpr::AO__opencl_atomic_exchange:
case AtomicExpr::AO__hip_atomic_exchange:
case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
case AtomicExpr::AO__atomic_load_n: case AtomicExpr::AO__atomic_load_n:
case AtomicExpr::AO__atomic_store_n: case AtomicExpr::AO__atomic_store_n:
@ -1079,7 +1112,9 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__c11_atomic_compare_exchange_weak: case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
case AtomicExpr::AO__c11_atomic_compare_exchange_strong: case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
case AtomicExpr::AO__atomic_compare_exchange: case AtomicExpr::AO__atomic_compare_exchange:
case AtomicExpr::AO__atomic_compare_exchange_n: case AtomicExpr::AO__atomic_compare_exchange_n:
LibCallName = "__atomic_compare_exchange"; LibCallName = "__atomic_compare_exchange";
@ -1101,6 +1136,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__opencl_atomic_exchange: case AtomicExpr::AO__opencl_atomic_exchange:
case AtomicExpr::AO__atomic_exchange_n: case AtomicExpr::AO__atomic_exchange_n:
case AtomicExpr::AO__atomic_exchange: case AtomicExpr::AO__atomic_exchange:
case AtomicExpr::AO__hip_atomic_exchange:
LibCallName = "__atomic_exchange"; LibCallName = "__atomic_exchange";
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
MemTy, E->getExprLoc(), TInfo.Width); MemTy, E->getExprLoc(), TInfo.Width);
@ -1109,6 +1145,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// void __atomic_store_N(T *mem, T val, int order) // void __atomic_store_N(T *mem, T val, int order)
case AtomicExpr::AO__c11_atomic_store: case AtomicExpr::AO__c11_atomic_store:
case AtomicExpr::AO__opencl_atomic_store: case AtomicExpr::AO__opencl_atomic_store:
case AtomicExpr::AO__hip_atomic_store:
case AtomicExpr::AO__atomic_store: case AtomicExpr::AO__atomic_store:
case AtomicExpr::AO__atomic_store_n: case AtomicExpr::AO__atomic_store_n:
LibCallName = "__atomic_store"; LibCallName = "__atomic_store";
@ -1121,6 +1158,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
// T __atomic_load_N(T *mem, int order) // T __atomic_load_N(T *mem, int order)
case AtomicExpr::AO__c11_atomic_load: case AtomicExpr::AO__c11_atomic_load:
case AtomicExpr::AO__opencl_atomic_load: case AtomicExpr::AO__opencl_atomic_load:
case AtomicExpr::AO__hip_atomic_load:
case AtomicExpr::AO__atomic_load: case AtomicExpr::AO__atomic_load:
case AtomicExpr::AO__atomic_load_n: case AtomicExpr::AO__atomic_load_n:
LibCallName = "__atomic_load"; LibCallName = "__atomic_load";
@ -1133,6 +1171,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__c11_atomic_fetch_add: case AtomicExpr::AO__c11_atomic_fetch_add:
case AtomicExpr::AO__opencl_atomic_fetch_add: case AtomicExpr::AO__opencl_atomic_fetch_add:
case AtomicExpr::AO__atomic_fetch_add: case AtomicExpr::AO__atomic_fetch_add:
case AtomicExpr::AO__hip_atomic_fetch_add:
LibCallName = "__atomic_fetch_add"; LibCallName = "__atomic_fetch_add";
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
LoweredMemTy, E->getExprLoc(), TInfo.Width); LoweredMemTy, E->getExprLoc(), TInfo.Width);
@ -1144,6 +1183,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_and: case AtomicExpr::AO__c11_atomic_fetch_and:
case AtomicExpr::AO__opencl_atomic_fetch_and: case AtomicExpr::AO__opencl_atomic_fetch_and:
case AtomicExpr::AO__hip_atomic_fetch_and:
case AtomicExpr::AO__atomic_fetch_and: case AtomicExpr::AO__atomic_fetch_and:
LibCallName = "__atomic_fetch_and"; LibCallName = "__atomic_fetch_and";
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
@ -1156,6 +1196,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_or: case AtomicExpr::AO__c11_atomic_fetch_or:
case AtomicExpr::AO__opencl_atomic_fetch_or: case AtomicExpr::AO__opencl_atomic_fetch_or:
case AtomicExpr::AO__hip_atomic_fetch_or:
case AtomicExpr::AO__atomic_fetch_or: case AtomicExpr::AO__atomic_fetch_or:
LibCallName = "__atomic_fetch_or"; LibCallName = "__atomic_fetch_or";
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
@ -1180,6 +1221,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_xor: case AtomicExpr::AO__c11_atomic_fetch_xor:
case AtomicExpr::AO__opencl_atomic_fetch_xor: case AtomicExpr::AO__opencl_atomic_fetch_xor:
case AtomicExpr::AO__hip_atomic_fetch_xor:
case AtomicExpr::AO__atomic_fetch_xor: case AtomicExpr::AO__atomic_fetch_xor:
LibCallName = "__atomic_fetch_xor"; LibCallName = "__atomic_fetch_xor";
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
@ -1190,6 +1232,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_min: case AtomicExpr::AO__c11_atomic_fetch_min:
case AtomicExpr::AO__atomic_fetch_min: case AtomicExpr::AO__atomic_fetch_min:
case AtomicExpr::AO__hip_atomic_fetch_min:
case AtomicExpr::AO__opencl_atomic_fetch_min: case AtomicExpr::AO__opencl_atomic_fetch_min:
LibCallName = E->getValueType()->isSignedIntegerType() LibCallName = E->getValueType()->isSignedIntegerType()
? "__atomic_fetch_min" ? "__atomic_fetch_min"
@ -1202,6 +1245,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_max: case AtomicExpr::AO__c11_atomic_fetch_max:
case AtomicExpr::AO__atomic_fetch_max: case AtomicExpr::AO__atomic_fetch_max:
case AtomicExpr::AO__hip_atomic_fetch_max:
case AtomicExpr::AO__opencl_atomic_fetch_max: case AtomicExpr::AO__opencl_atomic_fetch_max:
LibCallName = E->getValueType()->isSignedIntegerType() LibCallName = E->getValueType()->isSignedIntegerType()
? "__atomic_fetch_max" ? "__atomic_fetch_max"
@ -1291,10 +1335,12 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store || bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store ||
E->getOp() == AtomicExpr::AO__opencl_atomic_store || E->getOp() == AtomicExpr::AO__opencl_atomic_store ||
E->getOp() == AtomicExpr::AO__hip_atomic_store ||
E->getOp() == AtomicExpr::AO__atomic_store || E->getOp() == AtomicExpr::AO__atomic_store ||
E->getOp() == AtomicExpr::AO__atomic_store_n; E->getOp() == AtomicExpr::AO__atomic_store_n;
bool IsLoad = E->getOp() == AtomicExpr::AO__c11_atomic_load || bool IsLoad = E->getOp() == AtomicExpr::AO__c11_atomic_load ||
E->getOp() == AtomicExpr::AO__opencl_atomic_load || E->getOp() == AtomicExpr::AO__opencl_atomic_load ||
E->getOp() == AtomicExpr::AO__hip_atomic_load ||
E->getOp() == AtomicExpr::AO__atomic_load || E->getOp() == AtomicExpr::AO__atomic_load ||
E->getOp() == AtomicExpr::AO__atomic_load_n; E->getOp() == AtomicExpr::AO__atomic_load_n;

View File

@ -170,8 +170,9 @@ static Value *EmitNontemporalStore(CodeGenFunction &CGF, const CallExpr *E) {
// Convert the type of the pointer to a pointer to the stored type. // Convert the type of the pointer to a pointer to the stored type.
Val = CGF.EmitToMemory(Val, E->getArg(0)->getType()); Val = CGF.EmitToMemory(Val, E->getArg(0)->getType());
unsigned SrcAddrSpace = Address->getType()->getPointerAddressSpace();
Value *BC = CGF.Builder.CreateBitCast( Value *BC = CGF.Builder.CreateBitCast(
Address, llvm::PointerType::getUnqual(Val->getType()), "cast"); Address, llvm::PointerType::get(Val->getType(), SrcAddrSpace), "cast");
LValue LV = CGF.MakeNaturalAlignAddrLValue(BC, E->getArg(0)->getType()); LValue LV = CGF.MakeNaturalAlignAddrLValue(BC, E->getArg(0)->getType());
LV.setNontemporal(true); LV.setNontemporal(true);
CGF.EmitStoreOfScalar(Val, LV, false); CGF.EmitStoreOfScalar(Val, LV, false);

View File

@ -4510,6 +4510,9 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(
Address Replacement(CGF.Builder.CreateLoad(Pair.second), Address Replacement(CGF.Builder.CreateLoad(Pair.second),
CGF.getContext().getDeclAlign(Pair.first)); CGF.getContext().getDeclAlign(Pair.first));
Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; }); Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; });
if (auto *DI = CGF.getDebugInfo())
DI->EmitDeclareOfAutoVariable(Pair.first, Pair.second.getPointer(),
CGF.Builder, /*UsePointerValue*/ true);
} }
// Adjust mapping for internal locals by mapping actual memory instead of // Adjust mapping for internal locals by mapping actual memory instead of
// a pointer to this memory. // a pointer to this memory.

View File

@ -710,10 +710,25 @@ void CodeGenModule::Release() {
1); 1);
} }
if (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 || // Add module metadata for return address signing (ignoring
// non-leaf/all) and stack tagging. These are actually turned on by function
// attributes, but we use module metadata to emit build attributes. This is
// needed for LTO, where the function attributes are inside bitcode
// serialised into a global variable by the time build attributes are
// emitted, so we can't access them.
if (Context.getTargetInfo().hasFeature("ptrauth") &&
LangOpts.getSignReturnAddressScope() !=
LangOptions::SignReturnAddressScopeKind::None)
getModule().addModuleFlag(llvm::Module::Override,
"sign-return-address-buildattr", 1);
if (LangOpts.Sanitize.has(SanitizerKind::MemTag))
getModule().addModuleFlag(llvm::Module::Override,
"tag-stack-memory-buildattr", 1);
if (Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb ||
Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 ||
Arch == llvm::Triple::aarch64_be) { Arch == llvm::Triple::aarch64_be) {
getModule().addModuleFlag(llvm::Module::Error, getModule().addModuleFlag(llvm::Module::Error, "branch-target-enforcement",
"branch-target-enforcement",
LangOpts.BranchTargetEnforcement); LangOpts.BranchTargetEnforcement);
getModule().addModuleFlag(llvm::Module::Error, "sign-return-address", getModule().addModuleFlag(llvm::Module::Error, "sign-return-address",
@ -722,9 +737,11 @@ void CodeGenModule::Release() {
getModule().addModuleFlag(llvm::Module::Error, "sign-return-address-all", getModule().addModuleFlag(llvm::Module::Error, "sign-return-address-all",
LangOpts.isSignReturnAddressScopeAll()); LangOpts.isSignReturnAddressScopeAll());
getModule().addModuleFlag(llvm::Module::Error, if (Arch != llvm::Triple::thumb && Arch != llvm::Triple::thumbeb) {
"sign-return-address-with-bkey", getModule().addModuleFlag(llvm::Module::Error,
!LangOpts.isSignReturnAddressWithAKey()); "sign-return-address-with-bkey",
!LangOpts.isSignReturnAddressWithAKey());
}
} }
if (!CodeGenOpts.MemoryProfileOutput.empty()) { if (!CodeGenOpts.MemoryProfileOutput.empty()) {
@ -1266,6 +1283,20 @@ static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
(CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage); (CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage);
} }
static void AppendTargetClonesMangling(const CodeGenModule &CGM,
const TargetClonesAttr *Attr,
unsigned VersionIndex,
raw_ostream &Out) {
Out << '.';
StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
if (FeatureStr.startswith("arch="))
Out << "arch_" << FeatureStr.substr(sizeof("arch=") - 1);
else
Out << FeatureStr;
Out << '.' << Attr->getMangledIndex(VersionIndex);
}
static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD, static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
const NamedDecl *ND, const NamedDecl *ND,
bool OmitMultiVersionMangling = false) { bool OmitMultiVersionMangling = false) {
@ -1319,6 +1350,10 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
case MultiVersionKind::Target: case MultiVersionKind::Target:
AppendTargetMangling(CGM, FD->getAttr<TargetAttr>(), Out); AppendTargetMangling(CGM, FD->getAttr<TargetAttr>(), Out);
break; break;
case MultiVersionKind::TargetClones:
AppendTargetClonesMangling(CGM, FD->getAttr<TargetClonesAttr>(),
GD.getMultiVersionIndex(), Out);
break;
case MultiVersionKind::None: case MultiVersionKind::None:
llvm_unreachable("None multiversion type isn't valid here"); llvm_unreachable("None multiversion type isn't valid here");
} }
@ -1983,8 +2018,9 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD,
FD = FD ? FD->getMostRecentDecl() : FD; FD = FD ? FD->getMostRecentDecl() : FD;
const auto *TD = FD ? FD->getAttr<TargetAttr>() : nullptr; const auto *TD = FD ? FD->getAttr<TargetAttr>() : nullptr;
const auto *SD = FD ? FD->getAttr<CPUSpecificAttr>() : nullptr; const auto *SD = FD ? FD->getAttr<CPUSpecificAttr>() : nullptr;
const auto *TC = FD ? FD->getAttr<TargetClonesAttr>() : nullptr;
bool AddedAttr = false; bool AddedAttr = false;
if (TD || SD) { if (TD || SD || TC) {
llvm::StringMap<bool> FeatureMap; llvm::StringMap<bool> FeatureMap;
getContext().getFunctionFeatureMap(FeatureMap, GD); getContext().getFunctionFeatureMap(FeatureMap, GD);
@ -3226,6 +3262,12 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD,
for (unsigned I = 0; I < Spec->cpus_size(); ++I) for (unsigned I = 0; I < Spec->cpus_size(); ++I)
EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr); EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
// Requires multiple emits. // Requires multiple emits.
} else if (FD->isTargetClonesMultiVersion()) {
auto *Clone = FD->getAttr<TargetClonesAttr>();
for (unsigned I = 0; I < Clone->featuresStrs_size(); ++I)
if (Clone->isFirstOfVersion(I))
EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
EmitTargetClonesResolver(GD);
} else } else
EmitGlobalFunctionDefinition(GD, GV); EmitGlobalFunctionDefinition(GD, GV);
} }
@ -3307,6 +3349,63 @@ llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM,
return llvm::GlobalValue::WeakODRLinkage; return llvm::GlobalValue::WeakODRLinkage;
} }
void CodeGenModule::EmitTargetClonesResolver(GlobalDecl GD) {
const auto *FD = cast<FunctionDecl>(GD.getDecl());
assert(FD && "Not a FunctionDecl?");
const auto *TC = FD->getAttr<TargetClonesAttr>();
assert(TC && "Not a target_clones Function?");
QualType CanonTy = Context.getCanonicalType(FD->getType());
llvm::Type *DeclTy = getTypes().ConvertType(CanonTy);
if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
const CGFunctionInfo &FInfo = getTypes().arrangeCXXMethodDeclaration(CXXFD);
DeclTy = getTypes().GetFunctionType(FInfo);
}
llvm::Function *ResolverFunc;
if (getTarget().supportsIFunc()) {
auto *IFunc = cast<llvm::GlobalIFunc>(
GetOrCreateMultiVersionResolver(GD, DeclTy, FD));
ResolverFunc = cast<llvm::Function>(IFunc->getResolver());
} else
ResolverFunc =
cast<llvm::Function>(GetOrCreateMultiVersionResolver(GD, DeclTy, FD));
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
for (unsigned VersionIndex = 0; VersionIndex < TC->featuresStrs_size();
++VersionIndex) {
if (!TC->isFirstOfVersion(VersionIndex))
continue;
StringRef Version = TC->getFeatureStr(VersionIndex);
StringRef MangledName =
getMangledName(GD.getWithMultiVersionIndex(VersionIndex));
llvm::Constant *Func = GetGlobalValue(MangledName);
assert(Func &&
"Should have already been created before calling resolver emit");
StringRef Architecture;
llvm::SmallVector<StringRef, 1> Feature;
if (Version.startswith("arch="))
Architecture = Version.drop_front(sizeof("arch=") - 1);
else if (Version != "default")
Feature.push_back(Version);
Options.emplace_back(cast<llvm::Function>(Func), Architecture, Feature);
}
const TargetInfo &TI = getTarget();
std::stable_sort(
Options.begin(), Options.end(),
[&TI](const CodeGenFunction::MultiVersionResolverOption &LHS,
const CodeGenFunction::MultiVersionResolverOption &RHS) {
return TargetMVPriority(TI, LHS) > TargetMVPriority(TI, RHS);
});
CodeGenFunction CGF(*this);
CGF.EmitMultiVersionResolver(ResolverFunc, Options);
}
void CodeGenModule::emitMultiVersionFunctions() { void CodeGenModule::emitMultiVersionFunctions() {
std::vector<GlobalDecl> MVFuncsToEmit; std::vector<GlobalDecl> MVFuncsToEmit;
MultiVersionFuncs.swap(MVFuncsToEmit); MultiVersionFuncs.swap(MVFuncsToEmit);
@ -3511,8 +3610,25 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(
// Since this is the first time we've created this IFunc, make sure // Since this is the first time we've created this IFunc, make sure
// that we put this multiversioned function into the list to be // that we put this multiversioned function into the list to be
// replaced later if necessary (target multiversioning only). // replaced later if necessary (target multiversioning only).
if (!FD->isCPUDispatchMultiVersion() && !FD->isCPUSpecificMultiVersion()) if (FD->isTargetMultiVersion())
MultiVersionFuncs.push_back(GD); MultiVersionFuncs.push_back(GD);
else if (FD->isTargetClonesMultiVersion()) {
// In target_clones multiversioning, make sure we emit this if used.
auto DDI =
DeferredDecls.find(getMangledName(GD.getWithMultiVersionIndex(0)));
if (DDI != DeferredDecls.end()) {
addDeferredDeclToEmit(GD);
DeferredDecls.erase(DDI);
} else {
// Emit the symbol of the 1st variant, so that the deferred decls know we
// need it, otherwise the only global value will be the resolver/ifunc,
// which end up getting broken if we search for them with GetGlobalValue'.
GetOrCreateLLVMFunction(
getMangledName(GD.getWithMultiVersionIndex(0)), DeclTy, FD,
/*ForVTable=*/false, /*DontDefer=*/true,
/*IsThunk=*/false, llvm::AttributeList(), ForDefinition);
}
}
if (getTarget().supportsIFunc()) { if (getTarget().supportsIFunc()) {
llvm::Type *ResolverType = llvm::FunctionType::get( llvm::Type *ResolverType = llvm::FunctionType::get(

View File

@ -1500,6 +1500,7 @@ class CodeGenModule : public CodeGenTypeCache {
void EmitAliasDefinition(GlobalDecl GD); void EmitAliasDefinition(GlobalDecl GD);
void emitIFuncDefinition(GlobalDecl GD); void emitIFuncDefinition(GlobalDecl GD);
void emitCPUDispatchDefinition(GlobalDecl GD); void emitCPUDispatchDefinition(GlobalDecl GD);
void EmitTargetClonesResolver(GlobalDecl GD);
void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D); void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D);
void EmitObjCIvarInitializations(ObjCImplementationDecl *D); void EmitObjCIvarInitializations(ObjCImplementationDecl *D);

View File

@ -6364,6 +6364,26 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) if (!FD)
return; return;
auto *Fn = cast<llvm::Function>(GV);
if (const auto *TA = FD->getAttr<TargetAttr>()) {
ParsedTargetAttr Attr = TA->parse();
if (!Attr.BranchProtection.empty()) {
TargetInfo::BranchProtectionInfo BPI;
StringRef DiagMsg;
(void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
BPI, DiagMsg);
static const char *SignReturnAddrStr[] = {"none", "non-leaf", "all"};
assert(static_cast<unsigned>(BPI.SignReturnAddr) <= 2 &&
"Unexpected SignReturnAddressScopeKind");
Fn->addFnAttr("sign-return-address",
SignReturnAddrStr[static_cast<int>(BPI.SignReturnAddr)]);
Fn->addFnAttr("branch-target-enforcement",
BPI.BranchTargetEnforcement ? "true" : "false");
}
}
const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>(); const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>();
if (!Attr) if (!Attr)
@ -6379,8 +6399,6 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
case ARMInterruptAttr::UNDEF: Kind = "UNDEF"; break; case ARMInterruptAttr::UNDEF: Kind = "UNDEF"; break;
} }
llvm::Function *Fn = cast<llvm::Function>(GV);
Fn->addFnAttr("interrupt", Kind); Fn->addFnAttr("interrupt", Kind);
ARMABIInfo::ABIKind ABI = cast<ARMABIInfo>(getABIInfo()).getABIKind(); ARMABIInfo::ABIKind ABI = cast<ARMABIInfo>(getABIInfo()).getABIKind();
@ -9339,17 +9357,25 @@ AMDGPUTargetCodeGenInfo::getLLVMSyncScopeID(const LangOptions &LangOpts,
llvm::LLVMContext &Ctx) const { llvm::LLVMContext &Ctx) const {
std::string Name; std::string Name;
switch (Scope) { switch (Scope) {
case SyncScope::HIPSingleThread:
Name = "singlethread";
break;
case SyncScope::HIPWavefront:
case SyncScope::OpenCLSubGroup:
Name = "wavefront";
break;
case SyncScope::HIPWorkgroup:
case SyncScope::OpenCLWorkGroup: case SyncScope::OpenCLWorkGroup:
Name = "workgroup"; Name = "workgroup";
break; break;
case SyncScope::HIPAgent:
case SyncScope::OpenCLDevice: case SyncScope::OpenCLDevice:
Name = "agent"; Name = "agent";
break; break;
case SyncScope::HIPSystem:
case SyncScope::OpenCLAllSVMDevices: case SyncScope::OpenCLAllSVMDevices:
Name = ""; Name = "";
break; break;
case SyncScope::OpenCLSubGroup:
Name = "wavefront";
} }
if (Ordering != llvm::AtomicOrdering::SequentiallyConsistent) { if (Ordering != llvm::AtomicOrdering::SequentiallyConsistent) {

View File

@ -38,6 +38,7 @@
#include "ToolChains/NaCl.h" #include "ToolChains/NaCl.h"
#include "ToolChains/NetBSD.h" #include "ToolChains/NetBSD.h"
#include "ToolChains/OpenBSD.h" #include "ToolChains/OpenBSD.h"
#include "ToolChains/PPCFreeBSD.h"
#include "ToolChains/PPCLinux.h" #include "ToolChains/PPCLinux.h"
#include "ToolChains/PS4CPU.h" #include "ToolChains/PS4CPU.h"
#include "ToolChains/RISCVToolchain.h" #include "ToolChains/RISCVToolchain.h"
@ -5302,7 +5303,11 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
TC = std::make_unique<toolchains::NetBSD>(*this, Target, Args); TC = std::make_unique<toolchains::NetBSD>(*this, Target, Args);
break; break;
case llvm::Triple::FreeBSD: case llvm::Triple::FreeBSD:
TC = std::make_unique<toolchains::FreeBSD>(*this, Target, Args); if (Target.isPPC())
TC = std::make_unique<toolchains::PPCFreeBSDToolChain>(*this, Target,
Args);
else
TC = std::make_unique<toolchains::FreeBSD>(*this, Target, Args);
break; break;
case llvm::Triple::Minix: case llvm::Triple::Minix:
TC = std::make_unique<toolchains::Minix>(*this, Target, Args); TC = std::make_unique<toolchains::Minix>(*this, Target, Args);

View File

@ -403,7 +403,7 @@ shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
} }
/// Adds exception related arguments to the driver command arguments. There's a /// Adds exception related arguments to the driver command arguments. There's a
/// master flag, -fexceptions and also language specific flags to enable/disable /// main flag, -fexceptions and also language specific flags to enable/disable
/// C++ and Objective-C exceptions. This makes it possible to for example /// C++ and Objective-C exceptions. This makes it possible to for example
/// disable C++ exceptions but enable Objective-C exceptions. /// disable C++ exceptions but enable Objective-C exceptions.
static bool addExceptionArgs(const ArgList &Args, types::ID InputType, static bool addExceptionArgs(const ArgList &Args, types::ID InputType,
@ -1603,6 +1603,49 @@ void RenderARMABI(const Driver &D, const llvm::Triple &Triple,
} }
} }
static void CollectARMPACBTIOptions(const Driver &D, const ArgList &Args,
ArgStringList &CmdArgs, bool isAArch64) {
const Arg *A = isAArch64
? Args.getLastArg(options::OPT_msign_return_address_EQ,
options::OPT_mbranch_protection_EQ)
: Args.getLastArg(options::OPT_mbranch_protection_EQ);
if (!A)
return;
StringRef Scope, Key;
bool IndirectBranches;
if (A->getOption().matches(options::OPT_msign_return_address_EQ)) {
Scope = A->getValue();
if (!Scope.equals("none") && !Scope.equals("non-leaf") &&
!Scope.equals("all"))
D.Diag(diag::err_invalid_branch_protection)
<< Scope << A->getAsString(Args);
Key = "a_key";
IndirectBranches = false;
} else {
StringRef DiagMsg;
llvm::ARM::ParsedBranchProtection PBP;
if (!llvm::ARM::parseBranchProtection(A->getValue(), PBP, DiagMsg))
D.Diag(diag::err_invalid_branch_protection)
<< DiagMsg << A->getAsString(Args);
if (!isAArch64 && PBP.Key == "b_key")
D.Diag(diag::warn_unsupported_branch_protection)
<< "b-key" << A->getAsString(Args);
Scope = PBP.Scope;
Key = PBP.Key;
IndirectBranches = PBP.BranchTargetEnforcement;
}
CmdArgs.push_back(
Args.MakeArgString(Twine("-msign-return-address=") + Scope));
if (!Scope.equals("none"))
CmdArgs.push_back(
Args.MakeArgString(Twine("-msign-return-address-key=") + Key));
if (IndirectBranches)
CmdArgs.push_back("-mbranch-target-enforce");
}
void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args, void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
ArgStringList &CmdArgs, bool KernelOrKext) const { ArgStringList &CmdArgs, bool KernelOrKext) const {
RenderARMABI(getToolChain().getDriver(), Triple, Args, CmdArgs); RenderARMABI(getToolChain().getDriver(), Triple, Args, CmdArgs);
@ -1644,6 +1687,10 @@ void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
CmdArgs.push_back("-mcmse"); CmdArgs.push_back("-mcmse");
AddAAPCSVolatileBitfieldArgs(Args, CmdArgs); AddAAPCSVolatileBitfieldArgs(Args, CmdArgs);
// Enable/disable return address signing and indirect branch targets.
CollectARMPACBTIOptions(getToolChain().getDriver(), Args, CmdArgs,
false /*isAArch64*/);
} }
void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple, void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
@ -1783,40 +1830,8 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
} }
// Enable/disable return address signing and indirect branch targets. // Enable/disable return address signing and indirect branch targets.
if (Arg *A = Args.getLastArg(options::OPT_msign_return_address_EQ, CollectARMPACBTIOptions(getToolChain().getDriver(), Args, CmdArgs,
options::OPT_mbranch_protection_EQ)) { true /*isAArch64*/);
const Driver &D = getToolChain().getDriver();
StringRef Scope, Key;
bool IndirectBranches;
if (A->getOption().matches(options::OPT_msign_return_address_EQ)) {
Scope = A->getValue();
if (!Scope.equals("none") && !Scope.equals("non-leaf") &&
!Scope.equals("all"))
D.Diag(diag::err_invalid_branch_protection)
<< Scope << A->getAsString(Args);
Key = "a_key";
IndirectBranches = false;
} else {
StringRef Err;
llvm::AArch64::ParsedBranchProtection PBP;
if (!llvm::AArch64::parseBranchProtection(A->getValue(), PBP, Err))
D.Diag(diag::err_invalid_branch_protection)
<< Err << A->getAsString(Args);
Scope = PBP.Scope;
Key = PBP.Key;
IndirectBranches = PBP.BranchTargetEnforcement;
}
CmdArgs.push_back(
Args.MakeArgString(Twine("-msign-return-address=") + Scope));
CmdArgs.push_back(
Args.MakeArgString(Twine("-msign-return-address-key=") + Key));
if (IndirectBranches)
CmdArgs.push_back("-mbranch-target-enforce");
}
// Handle -msve_vector_bits=<bits> // Handle -msve_vector_bits=<bits>
if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) { if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) {
@ -5821,9 +5836,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden_static_local_var, Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden_static_local_var,
options::OPT_fno_visibility_inlines_hidden_static_local_var); options::OPT_fno_visibility_inlines_hidden_static_local_var);
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete_hidden); Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete_hidden);
Args.AddLastArg(CmdArgs, options::OPT_fnew_infallible);
Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ); Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
if (Args.hasFlag(options::OPT_fnew_infallible,
options::OPT_fno_new_infallible, false))
CmdArgs.push_back("-fnew-infallible");
if (Args.hasFlag(options::OPT_fno_operator_names, if (Args.hasFlag(options::OPT_fno_operator_names,
options::OPT_foperator_names, false)) options::OPT_foperator_names, false))
CmdArgs.push_back("-fno-operator-names"); CmdArgs.push_back("-fno-operator-names");
@ -5886,7 +5904,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// runtime. // runtime.
if (Args.hasFlag(options::OPT_fopenmp_target_new_runtime, if (Args.hasFlag(options::OPT_fopenmp_target_new_runtime,
options::OPT_fno_openmp_target_new_runtime, options::OPT_fno_openmp_target_new_runtime,
/*Default=*/false)) /*Default=*/!getToolChain().getTriple().isAMDGCN()))
CmdArgs.push_back("-fopenmp-target-new-runtime"); CmdArgs.push_back("-fopenmp-target-new-runtime");
// When in OpenMP offloading mode, enable debugging on the device. // When in OpenMP offloading mode, enable debugging on the device.
@ -6659,6 +6677,35 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->claim(); A->claim();
} }
// Turn -fplugin-arg-pluginname-key=value into
// -plugin-arg-pluginname key=value
// GCC has an actual plugin_argument struct with key/value pairs that it
// passes to its plugins, but we don't, so just pass it on as-is.
//
// The syntax for -fplugin-arg- is ambiguous if both plugin name and
// argument key are allowed to contain dashes. GCC therefore only
// allows dashes in the key. We do the same.
for (const Arg *A : Args.filtered(options::OPT_fplugin_arg)) {
auto ArgValue = StringRef(A->getValue());
auto FirstDashIndex = ArgValue.find('-');
StringRef PluginName = ArgValue.substr(0, FirstDashIndex);
StringRef Arg = ArgValue.substr(FirstDashIndex + 1);
A->claim();
if (FirstDashIndex == StringRef::npos || Arg.empty()) {
if (PluginName.empty()) {
D.Diag(diag::warn_drv_missing_plugin_name) << A->getAsString(Args);
} else {
D.Diag(diag::warn_drv_missing_plugin_arg)
<< PluginName << A->getAsString(Args);
}
continue;
}
CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-arg-") + PluginName));
CmdArgs.push_back(Args.MakeArgString(Arg));
}
// Forward -fpass-plugin=name.so to -cc1. // Forward -fpass-plugin=name.so to -cc1.
for (const Arg *A : Args.filtered(options::OPT_fpass_plugin_EQ)) { for (const Arg *A : Args.filtered(options::OPT_fpass_plugin_EQ)) {
CmdArgs.push_back( CmdArgs.push_back(

View File

@ -745,7 +745,7 @@ void CudaToolChain::addClangTargetOptions(
std::string BitcodeSuffix; std::string BitcodeSuffix;
if (DriverArgs.hasFlag(options::OPT_fopenmp_target_new_runtime, if (DriverArgs.hasFlag(options::OPT_fopenmp_target_new_runtime,
options::OPT_fno_openmp_target_new_runtime, false)) options::OPT_fno_openmp_target_new_runtime, true))
BitcodeSuffix = "new-nvptx-" + GpuArch.str(); BitcodeSuffix = "new-nvptx-" + GpuArch.str();
else else
BitcodeSuffix = "nvptx-" + GpuArch.str(); BitcodeSuffix = "nvptx-" + GpuArch.str();

View File

@ -32,7 +32,8 @@ void Flang::AddFortranDialectOptions(const ArgList &Args,
options::OPT_fxor_operator, options::OPT_fno_xor_operator, options::OPT_fxor_operator, options::OPT_fno_xor_operator,
options::OPT_falternative_parameter_statement, options::OPT_falternative_parameter_statement,
options::OPT_fdefault_real_8, options::OPT_fdefault_integer_8, options::OPT_fdefault_real_8, options::OPT_fdefault_integer_8,
options::OPT_fdefault_double_8, options::OPT_flarge_sizes}); options::OPT_fdefault_double_8, options::OPT_flarge_sizes,
options::OPT_fno_automatic});
} }
void Flang::AddPreprocessingOptions(const ArgList &Args, void Flang::AddPreprocessingOptions(const ArgList &Args,

View File

@ -391,7 +391,8 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple,
} }
ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const { ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const {
if (getTriple().getOSMajorVersion() >= 10) unsigned Major = getTriple().getOSMajorVersion();
if (Major >= 10 || Major == 0)
return ToolChain::CST_Libcxx; return ToolChain::CST_Libcxx;
return ToolChain::CST_Libstdcxx; return ToolChain::CST_Libstdcxx;
} }

View File

@ -421,6 +421,9 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
(Triple.getEnvironment() == llvm::Triple::MuslEABIHF || (Triple.getEnvironment() == llvm::Triple::MuslEABIHF ||
tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)) tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard))
ArchName += "hf"; ArchName += "hf";
if (Arch == llvm::Triple::ppc &&
Triple.getSubArch() == llvm::Triple::PPCSubArch_spe)
ArchName = "powerpc-sf";
return "/lib/ld-musl-" + ArchName + ".so.1"; return "/lib/ld-musl-" + ArchName + ".so.1";
} }

View File

@ -0,0 +1,28 @@
//===-- PPCFreeBSD.cpp - PowerPC ToolChain Implementations ------*- 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
//
//===----------------------------------------------------------------------===//
#include "PPCFreeBSD.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
#include "llvm/Support/Path.h"
using namespace clang::driver::toolchains;
using namespace llvm::opt;
void PPCFreeBSDToolChain::AddClangSystemIncludeArgs(
const ArgList &DriverArgs, ArgStringList &CC1Args) const {
if (!DriverArgs.hasArg(clang::driver::options::OPT_nostdinc) &&
!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
const Driver &D = getDriver();
SmallString<128> P(D.ResourceDir);
llvm::sys::path::append(P, "include", "ppc_wrappers");
addSystemInclude(DriverArgs, CC1Args, P);
}
FreeBSD::AddClangSystemIncludeArgs(DriverArgs, CC1Args);
}

View File

@ -0,0 +1,33 @@
//===--- PPCFreeBSD.h - PowerPC ToolChain Implementations -------*- 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_LIB_DRIVER_TOOLCHAINS_PPC_FREEBSD_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_PPC_FREEBSD_H
#include "FreeBSD.h"
namespace clang {
namespace driver {
namespace toolchains {
class LLVM_LIBRARY_VISIBILITY PPCFreeBSDToolChain : public FreeBSD {
public:
PPCFreeBSDToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args)
: FreeBSD(D, Triple, Args) {}
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
};
} // end namespace toolchains
} // end namespace driver
} // end namespace clang
#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_PPC_FREEBSD_H

View File

@ -80,6 +80,7 @@ class LLVM_LIBRARY_VISIBILITY PS4CPU : public Generic_ELF {
return LangOptions::SSPStrong; return LangOptions::SSPStrong;
} }
unsigned GetDefaultDwarfVersion() const override { return 4; }
llvm::DebuggerKind getDefaultDebuggerTuning() const override { llvm::DebuggerKind getDefaultDebuggerTuning() const override {
return llvm::DebuggerKind::SCE; return llvm::DebuggerKind::SCE;
} }

View File

@ -1984,9 +1984,17 @@ ContinuationIndenter::createBreakableToken(const FormatToken &Current,
} else if (Current.is(TT_LineComment) && } else if (Current.is(TT_LineComment) &&
(Current.Previous == nullptr || (Current.Previous == nullptr ||
Current.Previous->isNot(TT_ImplicitStringLiteral))) { Current.Previous->isNot(TT_ImplicitStringLiteral))) {
bool RegularComments = [&]() {
for (const FormatToken *T = &Current; T && T->is(TT_LineComment);
T = T->Next) {
if (!(T->TokenText.startswith("//") || T->TokenText.startswith("#")))
return false;
}
return true;
}();
if (!Style.ReflowComments || if (!Style.ReflowComments ||
CommentPragmasRegex.match(Current.TokenText.substr(2)) || CommentPragmasRegex.match(Current.TokenText.substr(2)) ||
switchesFormatting(Current)) switchesFormatting(Current) || !RegularComments)
return nullptr; return nullptr;
return std::make_unique<BreakableLineCommentSection>( return std::make_unique<BreakableLineCommentSection>(
Current, StartColumn, /*InPPDirective=*/false, Encoding, Style); Current, StartColumn, /*InPPDirective=*/false, Encoding, Style);
@ -2195,11 +2203,10 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
// When breaking before a tab character, it may be moved by a few columns, // When breaking before a tab character, it may be moved by a few columns,
// but will still be expanded to the next tab stop, so we don't save any // but will still be expanded to the next tab stop, so we don't save any
// columns. // columns.
if (NewRemainingTokenColumns == RemainingTokenColumns) { if (NewRemainingTokenColumns >= RemainingTokenColumns) {
// FIXME: Do we need to adjust the penalty? // FIXME: Do we need to adjust the penalty?
break; break;
} }
assert(NewRemainingTokenColumns < RemainingTokenColumns);
LLVM_DEBUG(llvm::dbgs() << " Breaking at: " << TailOffset + Split.first LLVM_DEBUG(llvm::dbgs() << " Breaking at: " << TailOffset + Split.first
<< ", " << Split.second << "\n"); << ", " << Split.second << "\n");

View File

@ -2988,9 +2988,8 @@ reformat(const FormatStyle &Style, StringRef Code,
// JSON only needs the formatting passing. // JSON only needs the formatting passing.
if (Style.isJson()) { if (Style.isJson()) {
std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
auto Env = auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
Environment::make(Code, FileName, Ranges, FirstStartColumn, NextStartColumn, LastStartColumn);
NextStartColumn, LastStartColumn);
if (!Env) if (!Env)
return {}; return {};
// Perform the actual formatting pass. // Perform the actual formatting pass.
@ -3118,9 +3117,7 @@ tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
auto Env = Environment::make(Code, FileName, Ranges); auto Env = Environment::make(Code, FileName, Ranges);
if (!Env) if (!Env)
return {}; return {};
return NamespaceEndCommentsFixer(*Env, Style) return NamespaceEndCommentsFixer(*Env, Style).process().first;
.process()
.first;
} }
tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
@ -3130,9 +3127,7 @@ tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
auto Env = Environment::make(Code, FileName, Ranges); auto Env = Environment::make(Code, FileName, Ranges);
if (!Env) if (!Env)
return {}; return {};
return UsingDeclarationsSorter(*Env, Style) return UsingDeclarationsSorter(*Env, Style).process().first;
.process()
.first;
} }
LangOptions getFormattingLangOpts(const FormatStyle &Style) { LangOptions getFormattingLangOpts(const FormatStyle &Style) {

View File

@ -76,6 +76,7 @@ namespace format {
TYPE(LineComment) \ TYPE(LineComment) \
TYPE(MacroBlockBegin) \ TYPE(MacroBlockBegin) \
TYPE(MacroBlockEnd) \ TYPE(MacroBlockEnd) \
TYPE(ModulePartitionColon) \
TYPE(NamespaceMacro) \ TYPE(NamespaceMacro) \
TYPE(NonNullAssertion) \ TYPE(NonNullAssertion) \
TYPE(NullCoalescingEqual) \ TYPE(NullCoalescingEqual) \

View File

@ -37,27 +37,40 @@ FormatTokenLexer::FormatTokenLexer(
getFormattingLangOpts(Style))); getFormattingLangOpts(Style)));
Lex->SetKeepWhitespaceMode(true); Lex->SetKeepWhitespaceMode(true);
for (const std::string &ForEachMacro : Style.ForEachMacros) for (const std::string &ForEachMacro : Style.ForEachMacros) {
Macros.insert({&IdentTable.get(ForEachMacro), TT_ForEachMacro}); auto Identifier = &IdentTable.get(ForEachMacro);
for (const std::string &IfMacro : Style.IfMacros) Macros.insert({Identifier, TT_ForEachMacro});
Macros.insert({&IdentTable.get(IfMacro), TT_IfMacro}); }
for (const std::string &AttributeMacro : Style.AttributeMacros) for (const std::string &IfMacro : Style.IfMacros) {
Macros.insert({&IdentTable.get(AttributeMacro), TT_AttributeMacro}); auto Identifier = &IdentTable.get(IfMacro);
for (const std::string &StatementMacro : Style.StatementMacros) Macros.insert({Identifier, TT_IfMacro});
Macros.insert({&IdentTable.get(StatementMacro), TT_StatementMacro}); }
for (const std::string &TypenameMacro : Style.TypenameMacros) for (const std::string &AttributeMacro : Style.AttributeMacros) {
Macros.insert({&IdentTable.get(TypenameMacro), TT_TypenameMacro}); auto Identifier = &IdentTable.get(AttributeMacro);
for (const std::string &NamespaceMacro : Style.NamespaceMacros) Macros.insert({Identifier, TT_AttributeMacro});
Macros.insert({&IdentTable.get(NamespaceMacro), TT_NamespaceMacro}); }
for (const std::string &StatementMacro : Style.StatementMacros) {
auto Identifier = &IdentTable.get(StatementMacro);
Macros.insert({Identifier, TT_StatementMacro});
}
for (const std::string &TypenameMacro : Style.TypenameMacros) {
auto Identifier = &IdentTable.get(TypenameMacro);
Macros.insert({Identifier, TT_TypenameMacro});
}
for (const std::string &NamespaceMacro : Style.NamespaceMacros) {
auto Identifier = &IdentTable.get(NamespaceMacro);
Macros.insert({Identifier, TT_NamespaceMacro});
}
for (const std::string &WhitespaceSensitiveMacro : for (const std::string &WhitespaceSensitiveMacro :
Style.WhitespaceSensitiveMacros) { Style.WhitespaceSensitiveMacros) {
Macros.insert( auto Identifier = &IdentTable.get(WhitespaceSensitiveMacro);
{&IdentTable.get(WhitespaceSensitiveMacro), TT_UntouchableMacroFunc}); Macros.insert({Identifier, TT_UntouchableMacroFunc});
} }
for (const std::string &StatementAttributeLikeMacro : for (const std::string &StatementAttributeLikeMacro :
Style.StatementAttributeLikeMacros) Style.StatementAttributeLikeMacros) {
Macros.insert({&IdentTable.get(StatementAttributeLikeMacro), auto Identifier = &IdentTable.get(StatementAttributeLikeMacro);
TT_StatementAttributeLikeMacro}); Macros.insert({Identifier, TT_StatementAttributeLikeMacro});
}
} }
ArrayRef<FormatToken *> FormatTokenLexer::lex() { ArrayRef<FormatToken *> FormatTokenLexer::lex() {
@ -739,6 +752,8 @@ bool FormatTokenLexer::tryMerge_TMacro() {
Tokens.pop_back(); Tokens.pop_back();
Tokens.pop_back(); Tokens.pop_back();
Tokens.back() = String; Tokens.back() = String;
if (FirstInLineIndex >= Tokens.size())
FirstInLineIndex = Tokens.size() - 1;
return true; return true;
} }

View File

@ -553,9 +553,7 @@ tooling::Replacements sortJavaScriptImports(const FormatStyle &Style,
auto Env = Environment::make(Code, FileName, Ranges); auto Env = Environment::make(Code, FileName, Ranges);
if (!Env) if (!Env)
return {}; return {};
return JavaScriptImportSorter(*Env, Style) return JavaScriptImportSorter(*Env, Style).process().first;
.process()
.first;
} }
} // end namespace format } // end namespace format

View File

@ -37,7 +37,7 @@ namespace format {
// FIXME: Instead of printing the diagnostic we should store it and have a // FIXME: Instead of printing the diagnostic we should store it and have a
// better way to return errors through the format APIs. // better way to return errors through the format APIs.
class FatalDiagnosticConsumer: public DiagnosticConsumer { class FatalDiagnosticConsumer : public DiagnosticConsumer {
public: public:
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) override { const Diagnostic &Info) override {
@ -71,7 +71,8 @@ Environment::make(StringRef Code, StringRef FileName,
} }
// Validate that we can get the buffer data without a fatal error. // Validate that we can get the buffer data without a fatal error.
Env->SM.getBufferData(Env->ID); Env->SM.getBufferData(Env->ID);
if (Diags.fatalError()) return nullptr; if (Diags.fatalError())
return nullptr;
return Env; return Env;
} }
@ -80,8 +81,7 @@ Environment::Environment(StringRef Code, StringRef FileName,
unsigned LastStartColumn) unsigned LastStartColumn)
: VirtualSM(new SourceManagerForFile(FileName, Code)), SM(VirtualSM->get()), : VirtualSM(new SourceManagerForFile(FileName, Code)), SM(VirtualSM->get()),
ID(VirtualSM->get().getMainFileID()), FirstStartColumn(FirstStartColumn), ID(VirtualSM->get().getMainFileID()), FirstStartColumn(FirstStartColumn),
NextStartColumn(NextStartColumn), LastStartColumn(LastStartColumn) { NextStartColumn(NextStartColumn), LastStartColumn(LastStartColumn) {}
}
TokenAnalyzer::TokenAnalyzer(const Environment &Env, const FormatStyle &Style) TokenAnalyzer::TokenAnalyzer(const Environment &Env, const FormatStyle &Style)
: Style(Style), Env(Env), : Style(Style), Env(Env),

View File

@ -314,10 +314,11 @@ class AnnotatingParser {
// //
// void (*FunctionPointer)(void); // void (*FunctionPointer)(void);
// void (&FunctionReference)(void); // void (&FunctionReference)(void);
// void (&&FunctionReference)(void);
// void (^ObjCBlock)(void); // void (^ObjCBlock)(void);
bool MightBeFunctionType = !Contexts[Contexts.size() - 2].IsExpression; bool MightBeFunctionType = !Contexts[Contexts.size() - 2].IsExpression;
bool ProbablyFunctionType = bool ProbablyFunctionType =
CurrentToken->isOneOf(tok::star, tok::amp, tok::caret); CurrentToken->isOneOf(tok::star, tok::amp, tok::ampamp, tok::caret);
bool HasMultipleLines = false; bool HasMultipleLines = false;
bool HasMultipleParametersOnALine = false; bool HasMultipleParametersOnALine = false;
bool MightBeObjCForRangeLoop = bool MightBeObjCForRangeLoop =
@ -902,9 +903,13 @@ class AnnotatingParser {
break; break;
} }
} }
if (Contexts.back().ColonIsDictLiteral || if (Line.First->isOneOf(Keywords.kw_module, Keywords.kw_import) ||
Style.Language == FormatStyle::LK_Proto || Line.First->startsSequence(tok::kw_export, Keywords.kw_module) ||
Style.Language == FormatStyle::LK_TextProto) { Line.First->startsSequence(tok::kw_export, Keywords.kw_import)) {
Tok->setType(TT_ModulePartitionColon);
} else if (Contexts.back().ColonIsDictLiteral ||
Style.Language == FormatStyle::LK_Proto ||
Style.Language == FormatStyle::LK_TextProto) {
Tok->setType(TT_DictLiteral); Tok->setType(TT_DictLiteral);
if (Style.Language == FormatStyle::LK_TextProto) { if (Style.Language == FormatStyle::LK_TextProto) {
if (FormatToken *Previous = Tok->getPreviousNonComment()) if (FormatToken *Previous = Tok->getPreviousNonComment())
@ -946,11 +951,15 @@ class AnnotatingParser {
!Line.First->isOneOf(tok::kw_enum, tok::kw_case, !Line.First->isOneOf(tok::kw_enum, tok::kw_case,
tok::kw_default)) { tok::kw_default)) {
FormatToken *Prev = Tok->getPreviousNonComment(); FormatToken *Prev = Tok->getPreviousNonComment();
if (!Prev)
break;
if (Prev->isOneOf(tok::r_paren, tok::kw_noexcept)) if (Prev->isOneOf(tok::r_paren, tok::kw_noexcept))
Tok->setType(TT_CtorInitializerColon); Tok->setType(TT_CtorInitializerColon);
else if (Prev->is(tok::kw_try)) { else if (Prev->is(tok::kw_try)) {
// Member initializer list within function try block. // Member initializer list within function try block.
FormatToken *PrevPrev = Prev->getPreviousNonComment(); FormatToken *PrevPrev = Prev->getPreviousNonComment();
if (!PrevPrev)
break;
if (PrevPrev && PrevPrev->isOneOf(tok::r_paren, tok::kw_noexcept)) if (PrevPrev && PrevPrev->isOneOf(tok::r_paren, tok::kw_noexcept))
Tok->setType(TT_CtorInitializerColon); Tok->setType(TT_CtorInitializerColon);
} else } else
@ -995,6 +1004,8 @@ class AnnotatingParser {
if (CurrentToken && CurrentToken->is(Keywords.kw_await)) if (CurrentToken && CurrentToken->is(Keywords.kw_await))
next(); next();
} }
if (Style.isCpp() && CurrentToken && CurrentToken->is(tok::kw_co_await))
next();
Contexts.back().ColonIsForRangeExpr = true; Contexts.back().ColonIsForRangeExpr = true;
next(); next();
if (!parseParens()) if (!parseParens())
@ -1578,6 +1589,8 @@ class AnnotatingParser {
if (TemplateCloser->is(tok::l_paren)) { if (TemplateCloser->is(tok::l_paren)) {
// No Matching Paren yet so skip to matching paren // No Matching Paren yet so skip to matching paren
TemplateCloser = untilMatchingParen(TemplateCloser); TemplateCloser = untilMatchingParen(TemplateCloser);
if (!TemplateCloser)
break;
} }
if (TemplateCloser->is(tok::less)) if (TemplateCloser->is(tok::less))
NestingLevel++; NestingLevel++;
@ -2336,16 +2349,15 @@ void TokenAnnotator::setCommentLineLevels(
if (NextNonCommentLine && CommentLine && if (NextNonCommentLine && CommentLine &&
NextNonCommentLine->First->NewlinesBefore <= 1 && NextNonCommentLine->First->NewlinesBefore <= 1 &&
NextNonCommentLine->First->OriginalColumn == NextNonCommentLine->First->OriginalColumn ==
AL->First->OriginalColumn) { AL->First->OriginalColumn) {
// Align comments for preprocessor lines with the # in column 0 if // Align comments for preprocessor lines with the # in column 0 if
// preprocessor lines are not indented. Otherwise, align with the next // preprocessor lines are not indented. Otherwise, align with the next
// line. // line.
AL->Level = AL->Level = (Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash &&
(Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash && (NextNonCommentLine->Type == LT_PreprocessorDirective ||
(NextNonCommentLine->Type == LT_PreprocessorDirective || NextNonCommentLine->Type == LT_ImportStatement))
NextNonCommentLine->Type == LT_ImportStatement)) ? 0
? 0 : NextNonCommentLine->Level;
: NextNonCommentLine->Level;
} else { } else {
NextNonCommentLine = AL->First->isNot(tok::r_brace) ? AL : nullptr; NextNonCommentLine = AL->First->isNot(tok::r_brace) ? AL : nullptr;
} }
@ -2639,8 +2651,8 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
if (Current->Role) if (Current->Role)
Current->Role->precomputeFormattingInfos(Current); Current->Role->precomputeFormattingInfos(Current);
if (Current->MatchingParen && if (Current->MatchingParen &&
Current->MatchingParen->opensBlockOrBlockTypeList(Style)) { Current->MatchingParen->opensBlockOrBlockTypeList(Style) &&
assert(IndentLevel > 0); IndentLevel > 0) {
--IndentLevel; --IndentLevel;
} }
Current->IndentLevel = IndentLevel; Current->IndentLevel = IndentLevel;
@ -2942,6 +2954,14 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Left.is(tok::kw_auto) && Right.isOneOf(tok::l_paren, tok::l_brace)) if (Left.is(tok::kw_auto) && Right.isOneOf(tok::l_paren, tok::l_brace))
return false; return false;
// operator co_await(x)
if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && Left.Previous &&
Left.Previous->is(tok::kw_operator))
return false;
// co_await (x), co_yield (x), co_return (x)
if (Left.isOneOf(tok::kw_co_await, tok::kw_co_yield, tok::kw_co_return) &&
Right.isNot(tok::semi))
return true;
// requires clause Concept1<T> && Concept2<T> // requires clause Concept1<T> && Concept2<T>
if (Left.is(TT_ConstraintJunctions) && Right.is(tok::identifier)) if (Left.is(TT_ConstraintJunctions) && Right.is(tok::identifier))
return true; return true;
@ -3159,9 +3179,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Left.isIf(Line.Type != LT_PreprocessorDirective)) if (Left.isIf(Line.Type != LT_PreprocessorDirective))
return Style.SpaceBeforeParensOptions.AfterControlStatements || return Style.SpaceBeforeParensOptions.AfterControlStatements ||
spaceRequiredBeforeParens(Right); spaceRequiredBeforeParens(Right);
// TODO add Operator overloading specific Options to
// SpaceBeforeParensOptions
if (Right.is(TT_OverloadedOperatorLParen))
return spaceRequiredBeforeParens(Right);
// Function declaration or definition // Function declaration or definition
if (Line.MightBeFunctionDecl && (Left.is(TT_FunctionDeclarationName) || if (Line.MightBeFunctionDecl && (Left.is(TT_FunctionDeclarationName))) {
Right.is(TT_OverloadedOperatorLParen))) {
if (Line.mightBeFunctionDefinition()) if (Line.mightBeFunctionDefinition())
return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName || return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName ||
spaceRequiredBeforeParens(Right); spaceRequiredBeforeParens(Right);
@ -3238,9 +3262,35 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
auto HasExistingWhitespace = [&Right]() { auto HasExistingWhitespace = [&Right]() {
return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd(); return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd();
}; };
if (Right.Tok.getIdentifierInfo() && Left.Tok.getIdentifierInfo()) if (Right.Tok.getIdentifierInfo() && Left.Tok.getIdentifierInfo())
return true; // Never ever merge two identifiers. return true; // Never ever merge two identifiers.
// Leave a space between * and /* to avoid C4138 `comment end` found outside
// of comment.
if (Left.is(tok::star) && Right.is(tok::comment))
return true;
if (Style.isCpp()) { if (Style.isCpp()) {
// Space between import <iostream>.
// or import .....;
if (Left.is(Keywords.kw_import) && Right.isOneOf(tok::less, tok::ellipsis))
return true;
// No space between module :.
if (Left.isOneOf(Keywords.kw_module, Keywords.kw_import) &&
Right.is(TT_ModulePartitionColon))
return true;
// No space between import foo:bar but keep a space between import :bar;
if (Left.is(tok::identifier) && Right.is(TT_ModulePartitionColon))
return false;
// No space between :bar;
if (Left.is(TT_ModulePartitionColon) &&
Right.isOneOf(tok::identifier, tok::kw_private))
return false;
if (Left.is(tok::ellipsis) && Right.is(tok::identifier) &&
Line.First->is(Keywords.kw_import))
return false;
if (Left.is(tok::kw_operator)) if (Left.is(tok::kw_operator))
return Right.is(tok::coloncolon); return Right.is(tok::coloncolon);
if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) && if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) &&

View File

@ -320,9 +320,9 @@ class LineJoiner {
} }
// Try to merge a control statement block with left brace wrapped // Try to merge a control statement block with left brace wrapped
if (I[1]->First->is(tok::l_brace) && if (I[1]->First->is(tok::l_brace) &&
(TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for, (TheLine->First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while,
tok::kw_switch, tok::kw_try, tok::kw_do, tok::kw_for, tok::kw_switch, tok::kw_try,
TT_ForEachMacro) || tok::kw_do, TT_ForEachMacro) ||
(TheLine->First->is(tok::r_brace) && TheLine->First->Next && (TheLine->First->is(tok::r_brace) && TheLine->First->Next &&
TheLine->First->Next->isOneOf(tok::kw_else, tok::kw_catch))) && TheLine->First->Next->isOneOf(tok::kw_else, tok::kw_catch))) &&
Style.BraceWrapping.AfterControlStatement == Style.BraceWrapping.AfterControlStatement ==
@ -335,7 +335,7 @@ class LineJoiner {
? 1 ? 1
: 0; : 0;
} else if (I[1]->First->is(tok::l_brace) && } else if (I[1]->First->is(tok::l_brace) &&
TheLine->First->isOneOf(tok::kw_if, tok::kw_while, TheLine->First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while,
tok::kw_for)) { tok::kw_for)) {
return (Style.BraceWrapping.AfterControlStatement == return (Style.BraceWrapping.AfterControlStatement ==
FormatStyle::BWACS_Always) FormatStyle::BWACS_Always)
@ -569,7 +569,7 @@ class LineJoiner {
// Check that the current line allows merging. This depends on whether we // Check that the current line allows merging. This depends on whether we
// are in a control flow statements as well as several style flags. // are in a control flow statements as well as several style flags.
if (Line.First->isOneOf(tok::kw_else, tok::kw_case) || if (Line.First->is(tok::kw_case) ||
(Line.First->Next && Line.First->Next->is(tok::kw_else))) (Line.First->Next && Line.First->Next->is(tok::kw_else)))
return 0; return 0;
// default: in switch statement // default: in switch statement
@ -578,20 +578,21 @@ class LineJoiner {
if (Tok && Tok->is(tok::colon)) if (Tok && Tok->is(tok::colon))
return 0; return 0;
} }
if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_try, if (Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while, tok::kw_do,
tok::kw___try, tok::kw_catch, tok::kw___finally, tok::kw_try, tok::kw___try, tok::kw_catch,
tok::kw_for, tok::r_brace, Keywords.kw___except)) { tok::kw___finally, tok::kw_for, tok::r_brace,
Keywords.kw___except)) {
if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never)
return 0; return 0;
// Don't merge when we can't except the case when // Don't merge when we can't except the case when
// the control statement block is empty // the control statement block is empty
if (!Style.AllowShortIfStatementsOnASingleLine && if (!Style.AllowShortIfStatementsOnASingleLine &&
Line.startsWith(tok::kw_if) && Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
!Style.BraceWrapping.AfterControlStatement && !Style.BraceWrapping.AfterControlStatement &&
!I[1]->First->is(tok::r_brace)) !I[1]->First->is(tok::r_brace))
return 0; return 0;
if (!Style.AllowShortIfStatementsOnASingleLine && if (!Style.AllowShortIfStatementsOnASingleLine &&
Line.startsWith(tok::kw_if) && Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
Style.BraceWrapping.AfterControlStatement == Style.BraceWrapping.AfterControlStatement ==
FormatStyle::BWACS_Always && FormatStyle::BWACS_Always &&
I + 2 != E && !I[2]->First->is(tok::r_brace)) I + 2 != E && !I[2]->First->is(tok::r_brace))
@ -676,7 +677,7 @@ class LineJoiner {
// { <-- current Line // { <-- current Line
// baz(); // baz();
// } // }
if (Line.First == Line.Last && if (Line.First == Line.Last && Line.First->isNot(TT_FunctionLBrace) &&
Style.BraceWrapping.AfterControlStatement == Style.BraceWrapping.AfterControlStatement ==
FormatStyle::BWACS_MultiLine) FormatStyle::BWACS_MultiLine)
return 0; return 0;

View File

@ -28,9 +28,28 @@ namespace format {
class FormatTokenSource { class FormatTokenSource {
public: public:
virtual ~FormatTokenSource() {} virtual ~FormatTokenSource() {}
// Returns the next token in the token stream.
virtual FormatToken *getNextToken() = 0; virtual FormatToken *getNextToken() = 0;
// Returns the token precedint the token returned by the last call to
// getNextToken() in the token stream, or nullptr if no such token exists.
virtual FormatToken *getPreviousToken() = 0;
// Returns the token that would be returned by the next call to
// getNextToken().
virtual FormatToken *peekNextToken() = 0;
// Returns whether we are at the end of the file.
// This can be different from whether getNextToken() returned an eof token
// when the FormatTokenSource is a view on a part of the token stream.
virtual bool isEOF() = 0;
// Gets the current position in the token stream, to be used by setPosition().
virtual unsigned getPosition() = 0; virtual unsigned getPosition() = 0;
// Resets the token stream to the state it was in when getPosition() returned
// Position, and return the token at that position in the stream.
virtual FormatToken *setPosition(unsigned Position) = 0; virtual FormatToken *setPosition(unsigned Position) = 0;
}; };
@ -108,6 +127,18 @@ class ScopedMacroState : public FormatTokenSource {
return Token; return Token;
} }
FormatToken *getPreviousToken() override {
return PreviousTokenSource->getPreviousToken();
}
FormatToken *peekNextToken() override {
if (eof())
return &FakeEOF;
return PreviousTokenSource->peekNextToken();
}
bool isEOF() override { return PreviousTokenSource->isEOF(); }
unsigned getPosition() override { return PreviousTokenSource->getPosition(); } unsigned getPosition() override { return PreviousTokenSource->getPosition(); }
FormatToken *setPosition(unsigned Position) override { FormatToken *setPosition(unsigned Position) override {
@ -199,16 +230,45 @@ class IndexedTokenSource : public FormatTokenSource {
: Tokens(Tokens), Position(-1) {} : Tokens(Tokens), Position(-1) {}
FormatToken *getNextToken() override { FormatToken *getNextToken() override {
if (Position >= 0 && Tokens[Position]->is(tok::eof)) {
LLVM_DEBUG({
llvm::dbgs() << "Next ";
dbgToken(Position);
});
return Tokens[Position];
}
++Position; ++Position;
LLVM_DEBUG({
llvm::dbgs() << "Next ";
dbgToken(Position);
});
return Tokens[Position]; return Tokens[Position];
} }
FormatToken *getPreviousToken() override {
assert(Position > 0);
return Tokens[Position - 1];
}
FormatToken *peekNextToken() override {
int Next = Position + 1;
LLVM_DEBUG({
llvm::dbgs() << "Peeking ";
dbgToken(Next);
});
return Tokens[Next];
}
bool isEOF() override { return Tokens[Position]->is(tok::eof); }
unsigned getPosition() override { unsigned getPosition() override {
LLVM_DEBUG(llvm::dbgs() << "Getting Position: " << Position << "\n");
assert(Position >= 0); assert(Position >= 0);
return Position; return Position;
} }
FormatToken *setPosition(unsigned P) override { FormatToken *setPosition(unsigned P) override {
LLVM_DEBUG(llvm::dbgs() << "Setting Position: " << P << "\n");
Position = P; Position = P;
return Tokens[Position]; return Tokens[Position];
} }
@ -216,6 +276,13 @@ class IndexedTokenSource : public FormatTokenSource {
void reset() { Position = -1; } void reset() { Position = -1; }
private: private:
void dbgToken(int Position, llvm::StringRef Indent = "") {
FormatToken *Tok = Tokens[Position];
llvm::dbgs() << Indent << "[" << Position
<< "] Token: " << Tok->Tok.getName() << " / " << Tok->TokenText
<< ", Macro: " << !!Tok->MacroCtx << "\n";
}
ArrayRef<FormatToken *> Tokens; ArrayRef<FormatToken *> Tokens;
int Position; int Position;
}; };
@ -399,7 +466,7 @@ void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
FormatToken *Next; FormatToken *Next;
do { do {
Next = Tokens->getNextToken(); Next = Tokens->getNextToken();
} while (Next && Next->is(tok::comment)); } while (Next->is(tok::comment));
FormatTok = Tokens->setPosition(StoredPosition); FormatTok = Tokens->setPosition(StoredPosition);
if (Next && Next->isNot(tok::colon)) { if (Next && Next->isNot(tok::colon)) {
// default not followed by ':' is not a case label; treat it like // default not followed by ':' is not a case label; treat it like
@ -875,10 +942,7 @@ void UnwrappedLineParser::parsePPEndIf() {
parsePPUnknown(); parsePPUnknown();
// If the #endif of a potential include guard is the last thing in the file, // If the #endif of a potential include guard is the last thing in the file,
// then we found an include guard. // then we found an include guard.
unsigned TokenPosition = Tokens->getPosition(); if (IncludeGuard == IG_Defined && PPBranchLevel == -1 && Tokens->isEOF() &&
FormatToken *PeekNext = AllTokens[TokenPosition];
if (IncludeGuard == IG_Defined && PPBranchLevel == -1 &&
PeekNext->is(tok::eof) &&
Style.IndentPPDirectives != FormatStyle::PPDIS_None) Style.IndentPPDirectives != FormatStyle::PPDIS_None)
IncludeGuard = IG_Found; IncludeGuard = IG_Found;
} }
@ -1050,6 +1114,35 @@ static bool isC78ParameterDecl(const FormatToken *Tok, const FormatToken *Next,
return Tok->Previous && Tok->Previous->isOneOf(tok::l_paren, tok::comma); return Tok->Previous && Tok->Previous->isOneOf(tok::l_paren, tok::comma);
} }
void UnwrappedLineParser::parseModuleImport() {
nextToken();
while (!eof()) {
if (FormatTok->is(tok::colon)) {
FormatTok->setType(TT_ModulePartitionColon);
}
// Handle import <foo/bar.h> as we would an include statement.
else if (FormatTok->is(tok::less)) {
nextToken();
while (!FormatTok->isOneOf(tok::semi, tok::greater, tok::eof)) {
// Mark tokens up to the trailing line comments as implicit string
// literals.
if (FormatTok->isNot(tok::comment) &&
!FormatTok->TokenText.startswith("//"))
FormatTok->setType(TT_ImplicitStringLiteral);
nextToken();
}
}
if (FormatTok->is(tok::semi)) {
nextToken();
break;
}
nextToken();
}
addUnwrappedLine();
return;
}
// readTokenWithJavaScriptASI reads the next token and terminates the current // readTokenWithJavaScriptASI reads the next token and terminates the current
// line if JavaScript Automatic Semicolon Insertion must // line if JavaScript Automatic Semicolon Insertion must
// happen between the current token and the next token. // happen between the current token and the next token.
@ -1097,7 +1190,6 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() {
} }
void UnwrappedLineParser::parseStructuralElement(bool IsTopLevel) { void UnwrappedLineParser::parseStructuralElement(bool IsTopLevel) {
assert(!FormatTok->is(tok::l_brace));
if (Style.Language == FormatStyle::LK_TableGen && if (Style.Language == FormatStyle::LK_TableGen &&
FormatTok->is(tok::pp_include)) { FormatTok->is(tok::pp_include)) {
nextToken(); nextToken();
@ -1249,6 +1341,10 @@ void UnwrappedLineParser::parseStructuralElement(bool IsTopLevel) {
addUnwrappedLine(); addUnwrappedLine();
return; return;
} }
if (Style.isCpp()) {
parseModuleImport();
return;
}
} }
if (Style.isCpp() && if (Style.isCpp() &&
FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals, FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
@ -1402,9 +1498,7 @@ void UnwrappedLineParser::parseStructuralElement(bool IsTopLevel) {
// declaration. // declaration.
if (!IsTopLevel || !Style.isCpp() || !Previous || FormatTok->is(tok::eof)) if (!IsTopLevel || !Style.isCpp() || !Previous || FormatTok->is(tok::eof))
break; break;
const unsigned Position = Tokens->getPosition() + 1; if (isC78ParameterDecl(FormatTok, Tokens->peekNextToken(), Previous)) {
assert(Position < AllTokens.size());
if (isC78ParameterDecl(FormatTok, AllTokens[Position], Previous)) {
addUnwrappedLine(); addUnwrappedLine();
return; return;
} }
@ -1488,7 +1582,7 @@ void UnwrappedLineParser::parseStructuralElement(bool IsTopLevel) {
unsigned StoredPosition = Tokens->getPosition(); unsigned StoredPosition = Tokens->getPosition();
FormatToken *Next = Tokens->getNextToken(); FormatToken *Next = Tokens->getNextToken();
FormatTok = Tokens->setPosition(StoredPosition); FormatTok = Tokens->setPosition(StoredPosition);
if (Next && !mustBeJSIdent(Keywords, Next)) { if (!mustBeJSIdent(Keywords, Next)) {
nextToken(); nextToken();
break; break;
} }
@ -2099,8 +2193,8 @@ void UnwrappedLineParser::parseIfThenElse() {
parseBlock(); parseBlock();
addUnwrappedLine(); addUnwrappedLine();
} else if (FormatTok->Tok.is(tok::kw_if)) { } else if (FormatTok->Tok.is(tok::kw_if)) {
FormatToken *Previous = AllTokens[Tokens->getPosition() - 1]; FormatToken *Previous = Tokens->getPreviousToken();
bool PrecededByComment = Previous->is(tok::comment); bool PrecededByComment = Previous && Previous->is(tok::comment);
if (PrecededByComment) { if (PrecededByComment) {
addUnwrappedLine(); addUnwrappedLine();
++Line->Level; ++Line->Level;
@ -2305,6 +2399,8 @@ void UnwrappedLineParser::parseForOrWhileLoop() {
if (Style.Language == FormatStyle::LK_JavaScript && if (Style.Language == FormatStyle::LK_JavaScript &&
FormatTok->is(Keywords.kw_await)) FormatTok->is(Keywords.kw_await))
nextToken(); nextToken();
if (Style.isCpp() && FormatTok->is(tok::kw_co_await))
nextToken();
if (FormatTok->Tok.is(tok::l_paren)) if (FormatTok->Tok.is(tok::l_paren))
parseParens(); parseParens();
if (FormatTok->Tok.is(tok::l_brace)) { if (FormatTok->Tok.is(tok::l_brace)) {
@ -2653,23 +2749,25 @@ bool UnwrappedLineParser::tryToParseSimpleAttribute() {
ScopedTokenPosition AutoPosition(Tokens); ScopedTokenPosition AutoPosition(Tokens);
FormatToken *Tok = Tokens->getNextToken(); FormatToken *Tok = Tokens->getNextToken();
// We already read the first [ check for the second. // We already read the first [ check for the second.
if (Tok && !Tok->is(tok::l_square)) { if (!Tok->is(tok::l_square)) {
return false; return false;
} }
// Double check that the attribute is just something // Double check that the attribute is just something
// fairly simple. // fairly simple.
while (Tok) { while (Tok->isNot(tok::eof)) {
if (Tok->is(tok::r_square)) { if (Tok->is(tok::r_square)) {
break; break;
} }
Tok = Tokens->getNextToken(); Tok = Tokens->getNextToken();
} }
if (Tok->is(tok::eof))
return false;
Tok = Tokens->getNextToken(); Tok = Tokens->getNextToken();
if (Tok && !Tok->is(tok::r_square)) { if (!Tok->is(tok::r_square)) {
return false; return false;
} }
Tok = Tokens->getNextToken(); Tok = Tokens->getNextToken();
if (Tok && Tok->is(tok::semi)) { if (Tok->is(tok::semi)) {
return false; return false;
} }
return true; return true;
@ -2682,7 +2780,7 @@ void UnwrappedLineParser::parseJavaEnumBody() {
unsigned StoredPosition = Tokens->getPosition(); unsigned StoredPosition = Tokens->getPosition();
bool IsSimple = true; bool IsSimple = true;
FormatToken *Tok = Tokens->getNextToken(); FormatToken *Tok = Tokens->getNextToken();
while (Tok) { while (!Tok->is(tok::eof)) {
if (Tok->is(tok::r_brace)) if (Tok->is(tok::r_brace))
break; break;
if (Tok->isOneOf(tok::l_brace, tok::semi)) { if (Tok->isOneOf(tok::l_brace, tok::semi)) {
@ -3292,6 +3390,20 @@ void UnwrappedLineParser::readToken(int LevelDifference) {
do { do {
FormatTok = Tokens->getNextToken(); FormatTok = Tokens->getNextToken();
assert(FormatTok); assert(FormatTok);
while (FormatTok->getType() == TT_ConflictStart ||
FormatTok->getType() == TT_ConflictEnd ||
FormatTok->getType() == TT_ConflictAlternative) {
if (FormatTok->getType() == TT_ConflictStart) {
conditionalCompilationStart(/*Unreachable=*/false);
} else if (FormatTok->getType() == TT_ConflictAlternative) {
conditionalCompilationAlternative();
} else if (FormatTok->getType() == TT_ConflictEnd) {
conditionalCompilationEnd();
}
FormatTok = Tokens->getNextToken();
FormatTok->MustBreakBefore = true;
}
while (!Line->InPPDirective && FormatTok->Tok.is(tok::hash) && while (!Line->InPPDirective && FormatTok->Tok.is(tok::hash) &&
(FormatTok->HasUnescapedNewline || FormatTok->IsFirst)) { (FormatTok->HasUnescapedNewline || FormatTok->IsFirst)) {
distributeComments(Comments, FormatTok); distributeComments(Comments, FormatTok);
@ -3313,19 +3425,6 @@ void UnwrappedLineParser::readToken(int LevelDifference) {
flushComments(isOnNewLine(*FormatTok)); flushComments(isOnNewLine(*FormatTok));
parsePPDirective(); parsePPDirective();
} }
while (FormatTok->getType() == TT_ConflictStart ||
FormatTok->getType() == TT_ConflictEnd ||
FormatTok->getType() == TT_ConflictAlternative) {
if (FormatTok->getType() == TT_ConflictStart) {
conditionalCompilationStart(/*Unreachable=*/false);
} else if (FormatTok->getType() == TT_ConflictAlternative) {
conditionalCompilationAlternative();
} else if (FormatTok->getType() == TT_ConflictEnd) {
conditionalCompilationEnd();
}
FormatTok = Tokens->getNextToken();
FormatTok->MustBreakBefore = true;
}
if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) && if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) &&
!Line->InPPDirective) { !Line->InPPDirective) {

View File

@ -110,6 +110,7 @@ class UnwrappedLineParser {
void parseCaseLabel(); void parseCaseLabel();
void parseSwitch(); void parseSwitch();
void parseNamespace(); void parseNamespace();
void parseModuleImport();
void parseNew(); void parseNew();
void parseAccessSpecifier(); void parseAccessSpecifier();
bool parseEnum(); bool parseEnum();

View File

@ -372,8 +372,6 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
if (ContinuedStringLiteral) if (ContinuedStringLiteral)
Changes[i].Spaces += Shift; Changes[i].Spaces += Shift;
assert(Shift >= 0);
Changes[i].StartOfTokenColumn += Shift; Changes[i].StartOfTokenColumn += Shift;
if (i + 1 != Changes.size()) if (i + 1 != Changes.size())
Changes[i + 1].PreviousEndOfTokenColumn += Shift; Changes[i + 1].PreviousEndOfTokenColumn += Shift;
@ -915,7 +913,8 @@ void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End,
Changes[i].StartOfBlockComment->StartOfTokenColumn - Changes[i].StartOfBlockComment->StartOfTokenColumn -
Changes[i].StartOfTokenColumn; Changes[i].StartOfTokenColumn;
} }
assert(Shift >= 0); if (Shift < 0)
continue;
Changes[i].Spaces += Shift; Changes[i].Spaces += Shift;
if (i + 1 != Changes.size()) if (i + 1 != Changes.size())
Changes[i + 1].PreviousEndOfTokenColumn += Shift; Changes[i + 1].PreviousEndOfTokenColumn += Shift;
@ -1270,10 +1269,10 @@ WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
void WhitespaceManager::generateChanges() { void WhitespaceManager::generateChanges() {
for (unsigned i = 0, e = Changes.size(); i != e; ++i) { for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
const Change &C = Changes[i]; const Change &C = Changes[i];
if (i > 0) { if (i > 0 && Changes[i - 1].OriginalWhitespaceRange.getBegin() ==
assert(Changes[i - 1].OriginalWhitespaceRange.getBegin() != C.OriginalWhitespaceRange.getBegin()) {
C.OriginalWhitespaceRange.getBegin() && // Do not generate two replacements for the same location.
"Generating two replacements for the same location"); continue;
} }
if (C.CreateReplacement) { if (C.CreateReplacement) {
std::string ReplacementText = C.PreviousLinePostfix; std::string ReplacementText = C.PreviousLinePostfix;

View File

@ -505,6 +505,11 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
if (LangOpts.HIP) { if (LangOpts.HIP) {
Builder.defineMacro("__HIP__"); Builder.defineMacro("__HIP__");
Builder.defineMacro("__HIPCC__"); Builder.defineMacro("__HIPCC__");
Builder.defineMacro("__HIP_MEMORY_SCOPE_SINGLETHREAD", "1");
Builder.defineMacro("__HIP_MEMORY_SCOPE_WAVEFRONT", "2");
Builder.defineMacro("__HIP_MEMORY_SCOPE_WORKGROUP", "3");
Builder.defineMacro("__HIP_MEMORY_SCOPE_AGENT", "4");
Builder.defineMacro("__HIP_MEMORY_SCOPE_SYSTEM", "5");
if (LangOpts.CUDAIsDevice) if (LangOpts.CUDAIsDevice)
Builder.defineMacro("__HIP_DEVICE_COMPILE__"); Builder.defineMacro("__HIP_DEVICE_COMPILE__");
} }

View File

@ -412,10 +412,13 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
std::unique_ptr<PrecompilePreambleAction> Act; std::unique_ptr<PrecompilePreambleAction> Act;
Act.reset(new PrecompilePreambleAction( Act.reset(new PrecompilePreambleAction(
StoreInMemory ? &Storage.asMemory().Data : nullptr, Callbacks)); StoreInMemory ? &Storage.asMemory().Data : nullptr, Callbacks));
Callbacks.BeforeExecute(*Clang);
if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
return BuildPreambleError::BeginSourceFileFailed; return BuildPreambleError::BeginSourceFileFailed;
// Performed after BeginSourceFile to ensure Clang->Preprocessor can be
// referenced in the callback.
Callbacks.BeforeExecute(*Clang);
std::unique_ptr<PPCallbacks> DelegatedPPCallbacks = std::unique_ptr<PPCallbacks> DelegatedPPCallbacks =
Callbacks.createPPCallbacks(); Callbacks.createPPCallbacks();
if (DelegatedPPCallbacks) if (DelegatedPPCallbacks)

View File

@ -633,7 +633,7 @@ static bool IsHeaderFile(const std::string &Filename) {
return false; return false;
} }
std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end()); std::string Ext = Filename.substr(DotPos + 1);
// C header: .h // C header: .h
// C++ header: .hh or .H; // C++ header: .hh or .H;
return Ext == "h" || Ext == "hh" || Ext == "H"; return Ext == "h" || Ext == "hh" || Ext == "H";

View File

@ -569,7 +569,7 @@ static bool IsHeaderFile(const std::string &Filename) {
return false; return false;
} }
std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end()); std::string Ext = Filename.substr(DotPos + 1);
// C header: .h // C header: .h
// C++ header: .hh or .H; // C++ header: .hh or .H;
return Ext == "h" || Ext == "hh" || Ext == "H"; return Ext == "h" || Ext == "hh" || Ext == "H";

View File

@ -19,6 +19,10 @@
#define __CR6_EQ_REV 1 #define __CR6_EQ_REV 1
#define __CR6_LT 2 #define __CR6_LT 2
#define __CR6_LT_REV 3 #define __CR6_LT_REV 3
#define __CR6_GT 4
#define __CR6_GT_REV 5
#define __CR6_SO 6
#define __CR6_SO_REV 7
/* Constants for vec_test_data_class */ /* Constants for vec_test_data_class */
#define __VEC_CLASS_FP_SUBNORMAL_N (1 << 0) #define __VEC_CLASS_FP_SUBNORMAL_N (1 << 0)
@ -8413,9 +8417,20 @@ static __inline__ vector float __ATTRS_o_ai vec_round(vector float __a) {
} }
#ifdef __VSX__ #ifdef __VSX__
#ifdef __XL_COMPAT_ALTIVEC__
static __inline__ vector double __ATTRS_o_ai vec_rint(vector double __a);
static __inline__ vector double __ATTRS_o_ai vec_round(vector double __a) {
double __fpscr = __builtin_readflm();
__builtin_setrnd(0);
vector double __rounded = vec_rint(__a);
__builtin_setflm(__fpscr);
return __rounded;
}
#else
static __inline__ vector double __ATTRS_o_ai vec_round(vector double __a) { static __inline__ vector double __ATTRS_o_ai vec_round(vector double __a) {
return __builtin_vsx_xvrdpi(__a); return __builtin_vsx_xvrdpi(__a);
} }
#endif
/* vec_rint */ /* vec_rint */
@ -19026,6 +19041,51 @@ vec_sra(vector signed __int128 __a, vector unsigned __int128 __b) {
#endif /* __SIZEOF_INT128__ */ #endif /* __SIZEOF_INT128__ */
#endif /* __POWER10_VECTOR__ */ #endif /* __POWER10_VECTOR__ */
#ifdef __POWER8_VECTOR__
#define __bcdadd(__a, __b, __ps) __builtin_ppc_bcdadd((__a), (__b), (__ps))
#define __bcdsub(__a, __b, __ps) __builtin_ppc_bcdsub((__a), (__b), (__ps))
static __inline__ long __bcdadd_ofl(vector unsigned char __a,
vector unsigned char __b) {
return __builtin_ppc_bcdadd_p(__CR6_SO, __a, __b);
}
static __inline__ long __bcdsub_ofl(vector unsigned char __a,
vector unsigned char __b) {
return __builtin_ppc_bcdsub_p(__CR6_SO, __a, __b);
}
static __inline__ long __bcd_invalid(vector unsigned char __a) {
return __builtin_ppc_bcdsub_p(__CR6_SO, __a, __a);
}
static __inline__ long __bcdcmpeq(vector unsigned char __a,
vector unsigned char __b) {
return __builtin_ppc_bcdsub_p(__CR6_EQ, __a, __b);
}
static __inline__ long __bcdcmplt(vector unsigned char __a,
vector unsigned char __b) {
return __builtin_ppc_bcdsub_p(__CR6_LT, __a, __b);
}
static __inline__ long __bcdcmpgt(vector unsigned char __a,
vector unsigned char __b) {
return __builtin_ppc_bcdsub_p(__CR6_GT, __a, __b);
}
static __inline__ long __bcdcmple(vector unsigned char __a,
vector unsigned char __b) {
return __builtin_ppc_bcdsub_p(__CR6_GT_REV, __a, __b);
}
static __inline__ long __bcdcmpge(vector unsigned char __a,
vector unsigned char __b) {
return __builtin_ppc_bcdsub_p(__CR6_LT_REV, __a, __b);
}
#endif // __POWER8_VECTOR__
#undef __ATTRS_o_ai #undef __ATTRS_o_ai
#endif /* __ALTIVEC_H */ #endif /* __ALTIVEC_H */

View File

@ -35,7 +35,7 @@
#ifndef EMMINTRIN_H_ #ifndef EMMINTRIN_H_
#define EMMINTRIN_H_ #define EMMINTRIN_H_
#if defined(__linux__) && defined(__ppc64__) #if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
#include <altivec.h> #include <altivec.h>
@ -2319,6 +2319,7 @@ _mm_castsi128_pd(__m128i __A)
#else #else
#include_next <emmintrin.h> #include_next <emmintrin.h>
#endif /* defined(__linux__) && defined(__ppc64__) */ #endif /* defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__)) \
*/
#endif /* EMMINTRIN_H_ */ #endif /* EMMINTRIN_H_ */

View File

@ -10,7 +10,7 @@
#ifndef _MM_MALLOC_H_INCLUDED #ifndef _MM_MALLOC_H_INCLUDED
#define _MM_MALLOC_H_INCLUDED #define _MM_MALLOC_H_INCLUDED
#if defined(__linux__) && defined(__ppc64__) #if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
#include <stdlib.h> #include <stdlib.h>

View File

@ -35,7 +35,7 @@
#ifndef _MMINTRIN_H_INCLUDED #ifndef _MMINTRIN_H_INCLUDED
#define _MMINTRIN_H_INCLUDED #define _MMINTRIN_H_INCLUDED
#if defined(__linux__) && defined(__ppc64__) #if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
#include <altivec.h> #include <altivec.h>
/* The Intel API is flexible enough that we must allow aliasing with other /* The Intel API is flexible enough that we must allow aliasing with other
@ -1445,6 +1445,7 @@ extern __inline __m64
#else #else
#include_next <mmintrin.h> #include_next <mmintrin.h>
#endif /* defined(__linux__) && defined(__ppc64__) */ #endif /* defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__)) \
*/
#endif /* _MMINTRIN_H_INCLUDED */ #endif /* _MMINTRIN_H_INCLUDED */

View File

@ -38,7 +38,7 @@
#ifndef PMMINTRIN_H_ #ifndef PMMINTRIN_H_
#define PMMINTRIN_H_ #define PMMINTRIN_H_
#if defined(__linux__) && defined(__ppc64__) #if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
/* We need definitions from the SSE2 and SSE header files*/ /* We need definitions from the SSE2 and SSE header files*/
#include <emmintrin.h> #include <emmintrin.h>
@ -145,6 +145,7 @@ _mm_lddqu_si128 (__m128i const *__P)
#else #else
#include_next <pmmintrin.h> #include_next <pmmintrin.h>
#endif /* defined(__linux__) && defined(__ppc64__) */ #endif /* defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__)) \
*/
#endif /* PMMINTRIN_H_ */ #endif /* PMMINTRIN_H_ */

View File

@ -29,7 +29,7 @@
#ifndef SMMINTRIN_H_ #ifndef SMMINTRIN_H_
#define SMMINTRIN_H_ #define SMMINTRIN_H_
#if defined(__linux__) && defined(__ppc64__) #if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
#include <altivec.h> #include <altivec.h>
#include <tmmintrin.h> #include <tmmintrin.h>
@ -104,6 +104,7 @@ extern __inline __m128i
#else #else
#include_next <smmintrin.h> #include_next <smmintrin.h>
#endif /* defined(__linux__) && defined(__ppc64__) */ #endif /* defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__)) \
*/
#endif /* _SMMINTRIN_H_ */ #endif /* _SMMINTRIN_H_ */

View File

@ -25,7 +25,7 @@
#ifndef TMMINTRIN_H_ #ifndef TMMINTRIN_H_
#define TMMINTRIN_H_ #define TMMINTRIN_H_
#if defined(__linux__) && defined(__ppc64__) #if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
#include <altivec.h> #include <altivec.h>
@ -490,6 +490,7 @@ _mm_mulhrs_pi16 (__m64 __A, __m64 __B)
#else #else
#include_next <tmmintrin.h> #include_next <tmmintrin.h>
#endif /* defined(__linux__) && defined(__ppc64__) */ #endif /* defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__)) \
*/
#endif /* TMMINTRIN_H_ */ #endif /* TMMINTRIN_H_ */

View File

@ -34,7 +34,7 @@
#ifndef _XMMINTRIN_H_INCLUDED #ifndef _XMMINTRIN_H_INCLUDED
#define _XMMINTRIN_H_INCLUDED #define _XMMINTRIN_H_INCLUDED
#if defined(__linux__) && defined(__ppc64__) #if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
/* Define four value permute mask */ /* Define four value permute mask */
#define _MM_SHUFFLE(w,x,y,z) (((w) << 6) | ((x) << 4) | ((y) << 2) | (z)) #define _MM_SHUFFLE(w,x,y,z) (((w) << 6) | ((x) << 4) | ((y) << 2) | (z))
@ -1838,6 +1838,7 @@ do { \
#else #else
#include_next <xmmintrin.h> #include_next <xmmintrin.h>
#endif /* defined(__linux__) && defined(__ppc64__) */ #endif /* defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__)) \
*/
#endif /* _XMMINTRIN_H_INCLUDED */ #endif /* _XMMINTRIN_H_INCLUDED */

View File

@ -12,8 +12,12 @@
/* If we're hosted, fall back to the system's stdatomic.h. FreeBSD, for /* If we're hosted, fall back to the system's stdatomic.h. FreeBSD, for
* example, already has a Clang-compatible stdatomic.h header. * example, already has a Clang-compatible stdatomic.h header.
*
* Exclude the MSVC path as well as the MSVC header as of the 14.31.30818
* explicitly disallows `stdatomic.h` in the C mode via an `#error`. Fallback
* to the clang resource header until that is fully supported.
*/ */
#if __STDC_HOSTED__ && __has_include_next(<stdatomic.h>) #if __STDC_HOSTED__ && __has_include_next(<stdatomic.h>) && !defined(_MSC_VER)
# include_next <stdatomic.h> # include_next <stdatomic.h>
#else #else

View File

@ -6978,13 +6978,13 @@ void Parser::ParseParameterDeclarationClause(
// //
// We care about case 1) where the declarator type should be known, and // We care about case 1) where the declarator type should be known, and
// the identifier should be null. // the identifier should be null.
if (!ParmDeclarator.isInvalidType() && !ParmDeclarator.hasName()) { if (!ParmDeclarator.isInvalidType() && !ParmDeclarator.hasName() &&
if (Tok.getIdentifierInfo() && Tok.isNot(tok::raw_identifier) && !Tok.isAnnotation() &&
Tok.getIdentifierInfo()->isKeyword(getLangOpts())) { Tok.getIdentifierInfo() &&
Diag(Tok, diag::err_keyword_as_parameter) << PP.getSpelling(Tok); Tok.getIdentifierInfo()->isKeyword(getLangOpts())) {
// Consume the keyword. Diag(Tok, diag::err_keyword_as_parameter) << PP.getSpelling(Tok);
ConsumeToken(); // Consume the keyword.
} ConsumeToken();
} }
// Inform the actions module about the parameter declarator, so it gets // Inform the actions module about the parameter declarator, so it gets
// added to the current scope. // added to the current scope.

View File

@ -2108,6 +2108,9 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
CoawaitLoc = SourceLocation(); CoawaitLoc = SourceLocation();
} }
if (CoawaitLoc.isValid() && getLangOpts().CPlusPlus20)
Diag(CoawaitLoc, diag::warn_deprecated_for_co_await);
// We need to perform most of the semantic analysis for a C++0x for-range // We need to perform most of the semantic analysis for a C++0x for-range
// statememt before parsing the body, in order to be able to deduce the type // statememt before parsing the body, in order to be able to deduce the type
// of an auto-typed loop variable. // of an auto-typed loop variable.

View File

@ -464,7 +464,7 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
// No more CFGElements in the block? // No more CFGElements in the block?
if (ri == re) { if (ri == re) {
const Stmt *Term = B.getTerminatorStmt(); const Stmt *Term = B.getTerminatorStmt();
if (Term && isa<CXXTryStmt>(Term)) { if (Term && (isa<CXXTryStmt>(Term) || isa<ObjCAtTryStmt>(Term))) {
HasAbnormalEdge = true; HasAbnormalEdge = true;
continue; continue;
} }

View File

@ -5297,6 +5297,7 @@ static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) {
case AtomicExpr::AO__c11_atomic_load: case AtomicExpr::AO__c11_atomic_load:
case AtomicExpr::AO__opencl_atomic_load: case AtomicExpr::AO__opencl_atomic_load:
case AtomicExpr::AO__hip_atomic_load:
case AtomicExpr::AO__atomic_load_n: case AtomicExpr::AO__atomic_load_n:
case AtomicExpr::AO__atomic_load: case AtomicExpr::AO__atomic_load:
return OrderingCABI != llvm::AtomicOrderingCABI::release && return OrderingCABI != llvm::AtomicOrderingCABI::release &&
@ -5304,6 +5305,7 @@ static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) {
case AtomicExpr::AO__c11_atomic_store: case AtomicExpr::AO__c11_atomic_store:
case AtomicExpr::AO__opencl_atomic_store: case AtomicExpr::AO__opencl_atomic_store:
case AtomicExpr::AO__hip_atomic_store:
case AtomicExpr::AO__atomic_store: case AtomicExpr::AO__atomic_store:
case AtomicExpr::AO__atomic_store_n: case AtomicExpr::AO__atomic_store_n:
return OrderingCABI != llvm::AtomicOrderingCABI::consume && return OrderingCABI != llvm::AtomicOrderingCABI::consume &&
@ -5380,6 +5382,8 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
"need to update code for modified C11 atomics"); "need to update code for modified C11 atomics");
bool IsOpenCL = Op >= AtomicExpr::AO__opencl_atomic_init && bool IsOpenCL = Op >= AtomicExpr::AO__opencl_atomic_init &&
Op <= AtomicExpr::AO__opencl_atomic_fetch_max; Op <= AtomicExpr::AO__opencl_atomic_fetch_max;
bool IsHIP = Op >= AtomicExpr::AO__hip_atomic_load &&
Op <= AtomicExpr::AO__hip_atomic_fetch_max;
bool IsC11 = (Op >= AtomicExpr::AO__c11_atomic_init && bool IsC11 = (Op >= AtomicExpr::AO__c11_atomic_init &&
Op <= AtomicExpr::AO__c11_atomic_fetch_min) || Op <= AtomicExpr::AO__c11_atomic_fetch_min) ||
IsOpenCL; IsOpenCL;
@ -5397,6 +5401,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
case AtomicExpr::AO__c11_atomic_load: case AtomicExpr::AO__c11_atomic_load:
case AtomicExpr::AO__opencl_atomic_load: case AtomicExpr::AO__opencl_atomic_load:
case AtomicExpr::AO__hip_atomic_load:
case AtomicExpr::AO__atomic_load_n: case AtomicExpr::AO__atomic_load_n:
Form = Load; Form = Load;
break; break;
@ -5407,11 +5412,14 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
case AtomicExpr::AO__c11_atomic_store: case AtomicExpr::AO__c11_atomic_store:
case AtomicExpr::AO__opencl_atomic_store: case AtomicExpr::AO__opencl_atomic_store:
case AtomicExpr::AO__hip_atomic_store:
case AtomicExpr::AO__atomic_store: case AtomicExpr::AO__atomic_store:
case AtomicExpr::AO__atomic_store_n: case AtomicExpr::AO__atomic_store_n:
Form = Copy; Form = Copy;
break; break;
case AtomicExpr::AO__hip_atomic_fetch_add:
case AtomicExpr::AO__hip_atomic_fetch_min:
case AtomicExpr::AO__hip_atomic_fetch_max:
case AtomicExpr::AO__c11_atomic_fetch_add: case AtomicExpr::AO__c11_atomic_fetch_add:
case AtomicExpr::AO__c11_atomic_fetch_sub: case AtomicExpr::AO__c11_atomic_fetch_sub:
case AtomicExpr::AO__opencl_atomic_fetch_add: case AtomicExpr::AO__opencl_atomic_fetch_add:
@ -5426,6 +5434,9 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
case AtomicExpr::AO__c11_atomic_fetch_and: case AtomicExpr::AO__c11_atomic_fetch_and:
case AtomicExpr::AO__c11_atomic_fetch_or: case AtomicExpr::AO__c11_atomic_fetch_or:
case AtomicExpr::AO__c11_atomic_fetch_xor: case AtomicExpr::AO__c11_atomic_fetch_xor:
case AtomicExpr::AO__hip_atomic_fetch_and:
case AtomicExpr::AO__hip_atomic_fetch_or:
case AtomicExpr::AO__hip_atomic_fetch_xor:
case AtomicExpr::AO__c11_atomic_fetch_nand: case AtomicExpr::AO__c11_atomic_fetch_nand:
case AtomicExpr::AO__opencl_atomic_fetch_and: case AtomicExpr::AO__opencl_atomic_fetch_and:
case AtomicExpr::AO__opencl_atomic_fetch_or: case AtomicExpr::AO__opencl_atomic_fetch_or:
@ -5452,6 +5463,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
break; break;
case AtomicExpr::AO__c11_atomic_exchange: case AtomicExpr::AO__c11_atomic_exchange:
case AtomicExpr::AO__hip_atomic_exchange:
case AtomicExpr::AO__opencl_atomic_exchange: case AtomicExpr::AO__opencl_atomic_exchange:
case AtomicExpr::AO__atomic_exchange_n: case AtomicExpr::AO__atomic_exchange_n:
Form = Xchg; Form = Xchg;
@ -5463,8 +5475,10 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
case AtomicExpr::AO__c11_atomic_compare_exchange_strong: case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
case AtomicExpr::AO__c11_atomic_compare_exchange_weak: case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
Form = C11CmpXchg; Form = C11CmpXchg;
break; break;
@ -5475,7 +5489,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
} }
unsigned AdjustedNumArgs = NumArgs[Form]; unsigned AdjustedNumArgs = NumArgs[Form];
if (IsOpenCL && Op != AtomicExpr::AO__opencl_atomic_init) if ((IsOpenCL || IsHIP) && Op != AtomicExpr::AO__opencl_atomic_init)
++AdjustedNumArgs; ++AdjustedNumArgs;
// Check we have the right number of arguments. // Check we have the right number of arguments.
if (Args.size() < AdjustedNumArgs) { if (Args.size() < AdjustedNumArgs) {
@ -5532,8 +5546,8 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
// For an arithmetic operation, the implied arithmetic must be well-formed. // For an arithmetic operation, the implied arithmetic must be well-formed.
if (Form == Arithmetic) { if (Form == Arithmetic) {
// GCC does not enforce these rules for GNU atomics, but we do, because if // GCC does not enforce these rules for GNU atomics, but we do to help catch
// we didn't it would be very confusing. FIXME: For whom? How so? // trivial type errors.
auto IsAllowedValueType = [&](QualType ValType) { auto IsAllowedValueType = [&](QualType ValType) {
if (ValType->isIntegerType()) if (ValType->isIntegerType())
return true; return true;
@ -5574,8 +5588,9 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
if (!IsC11 && !AtomTy.isTriviallyCopyableType(Context) && if (!IsC11 && !AtomTy.isTriviallyCopyableType(Context) &&
!AtomTy->isScalarType()) { !AtomTy->isScalarType()) {
// For GNU atomics, require a trivially-copyable type. This is not part of // For GNU atomics, require a trivially-copyable type. This is not part of
// the GNU atomics specification, but we enforce it, because if we didn't it // the GNU atomics specification but we enforce it for consistency with
// would be very confusing. FIXME: For whom? How so? // other atomics which generally all require a trivially-copyable type. This
// is because atomics just copy bits.
Diag(ExprRange.getBegin(), diag::err_atomic_op_needs_trivial_copy) Diag(ExprRange.getBegin(), diag::err_atomic_op_needs_trivial_copy)
<< Ptr->getType() << Ptr->getSourceRange(); << Ptr->getType() << Ptr->getSourceRange();
return ExprError(); return ExprError();
@ -5614,7 +5629,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
// arguments are actually passed as pointers. // arguments are actually passed as pointers.
QualType ByValType = ValType; // 'CP' QualType ByValType = ValType; // 'CP'
bool IsPassedByAddress = false; bool IsPassedByAddress = false;
if (!IsC11 && !IsN) { if (!IsC11 && !IsHIP && !IsN) {
ByValType = Ptr->getType(); ByValType = Ptr->getType();
IsPassedByAddress = true; IsPassedByAddress = true;
} }
@ -5793,11 +5808,14 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
if ((Op == AtomicExpr::AO__c11_atomic_load || if ((Op == AtomicExpr::AO__c11_atomic_load ||
Op == AtomicExpr::AO__c11_atomic_store || Op == AtomicExpr::AO__c11_atomic_store ||
Op == AtomicExpr::AO__opencl_atomic_load || Op == AtomicExpr::AO__opencl_atomic_load ||
Op == AtomicExpr::AO__opencl_atomic_store ) && Op == AtomicExpr::AO__hip_atomic_load ||
Op == AtomicExpr::AO__opencl_atomic_store ||
Op == AtomicExpr::AO__hip_atomic_store) &&
Context.AtomicUsesUnsupportedLibcall(AE)) Context.AtomicUsesUnsupportedLibcall(AE))
Diag(AE->getBeginLoc(), diag::err_atomic_load_store_uses_lib) Diag(AE->getBeginLoc(), diag::err_atomic_load_store_uses_lib)
<< ((Op == AtomicExpr::AO__c11_atomic_load || << ((Op == AtomicExpr::AO__c11_atomic_load ||
Op == AtomicExpr::AO__opencl_atomic_load) Op == AtomicExpr::AO__opencl_atomic_load ||
Op == AtomicExpr::AO__hip_atomic_load)
? 0 ? 0
: 1); : 1);

View File

@ -10268,13 +10268,9 @@ static bool checkNonMultiVersionCompatAttributes(Sema &S,
const FunctionDecl *FD, const FunctionDecl *FD,
const FunctionDecl *CausedFD, const FunctionDecl *CausedFD,
MultiVersionKind MVType) { MultiVersionKind MVType) {
bool IsCPUSpecificCPUDispatchMVType = const auto Diagnose = [FD, CausedFD, MVType](Sema &S, const Attr *A) {
MVType == MultiVersionKind::CPUDispatch ||
MVType == MultiVersionKind::CPUSpecific;
const auto Diagnose = [FD, CausedFD, IsCPUSpecificCPUDispatchMVType](
Sema &S, const Attr *A) {
S.Diag(FD->getLocation(), diag::err_multiversion_disallowed_other_attr) S.Diag(FD->getLocation(), diag::err_multiversion_disallowed_other_attr)
<< IsCPUSpecificCPUDispatchMVType << A; << static_cast<unsigned>(MVType) << A;
if (CausedFD) if (CausedFD)
S.Diag(CausedFD->getLocation(), diag::note_multiversioning_caused_here); S.Diag(CausedFD->getLocation(), diag::note_multiversioning_caused_here);
return true; return true;
@ -10292,6 +10288,10 @@ static bool checkNonMultiVersionCompatAttributes(Sema &S,
if (MVType != MultiVersionKind::Target) if (MVType != MultiVersionKind::Target)
return Diagnose(S, A); return Diagnose(S, A);
break; break;
case attr::TargetClones:
if (MVType != MultiVersionKind::TargetClones)
return Diagnose(S, A);
break;
default: default:
if (!AttrCompatibleWithMultiVersion(A->getKind(), MVType)) if (!AttrCompatibleWithMultiVersion(A->getKind(), MVType))
return Diagnose(S, A); return Diagnose(S, A);
@ -10318,6 +10318,7 @@ bool Sema::areMultiversionVariantFunctionsCompatible(
DefaultedFuncs = 6, DefaultedFuncs = 6,
ConstexprFuncs = 7, ConstexprFuncs = 7,
ConstevalFuncs = 8, ConstevalFuncs = 8,
Lambda = 9,
}; };
enum Different { enum Different {
CallingConv = 0, CallingConv = 0,
@ -10445,7 +10446,7 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
S.PDiag(diag::note_multiversioning_caused_here)), S.PDiag(diag::note_multiversioning_caused_here)),
PartialDiagnosticAt(NewFD->getLocation(), PartialDiagnosticAt(NewFD->getLocation(),
S.PDiag(diag::err_multiversion_doesnt_support) S.PDiag(diag::err_multiversion_doesnt_support)
<< IsCPUSpecificCPUDispatchMVType), << static_cast<unsigned>(MVType)),
PartialDiagnosticAt(NewFD->getLocation(), PartialDiagnosticAt(NewFD->getLocation(),
S.PDiag(diag::err_multiversion_diff)), S.PDiag(diag::err_multiversion_diff)),
/*TemplatesSupported=*/false, /*TemplatesSupported=*/false,
@ -10574,21 +10575,30 @@ static bool CheckTargetCausesMultiVersioning(
return false; return false;
} }
static bool MultiVersionTypesCompatible(MultiVersionKind Old,
MultiVersionKind New) {
if (Old == New || Old == MultiVersionKind::None ||
New == MultiVersionKind::None)
return true;
return (Old == MultiVersionKind::CPUDispatch &&
New == MultiVersionKind::CPUSpecific) ||
(Old == MultiVersionKind::CPUSpecific &&
New == MultiVersionKind::CPUDispatch);
}
/// Check the validity of a new function declaration being added to an existing /// Check the validity of a new function declaration being added to an existing
/// multiversioned declaration collection. /// multiversioned declaration collection.
static bool CheckMultiVersionAdditionalDecl( static bool CheckMultiVersionAdditionalDecl(
Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD,
MultiVersionKind NewMVType, const TargetAttr *NewTA, MultiVersionKind NewMVType, const TargetAttr *NewTA,
const CPUDispatchAttr *NewCPUDisp, const CPUSpecificAttr *NewCPUSpec, const CPUDispatchAttr *NewCPUDisp, const CPUSpecificAttr *NewCPUSpec,
bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious, const TargetClonesAttr *NewClones, bool &Redeclaration, NamedDecl *&OldDecl,
LookupResult &Previous) { bool &MergeTypeWithPrevious, LookupResult &Previous) {
MultiVersionKind OldMVType = OldFD->getMultiVersionKind(); MultiVersionKind OldMVType = OldFD->getMultiVersionKind();
// Disallow mixing of multiversioning types. // Disallow mixing of multiversioning types.
if ((OldMVType == MultiVersionKind::Target && if (!MultiVersionTypesCompatible(OldMVType, NewMVType)) {
NewMVType != MultiVersionKind::Target) ||
(NewMVType == MultiVersionKind::Target &&
OldMVType != MultiVersionKind::Target)) {
S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed); S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed);
S.Diag(OldFD->getLocation(), diag::note_previous_declaration); S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
NewFD->setInvalidDecl(); NewFD->setInvalidDecl();
@ -10613,7 +10623,12 @@ static bool CheckMultiVersionAdditionalDecl(
if (S.IsOverload(NewFD, CurFD, UseMemberUsingDeclRules)) if (S.IsOverload(NewFD, CurFD, UseMemberUsingDeclRules))
continue; continue;
if (NewMVType == MultiVersionKind::Target) { switch (NewMVType) {
case MultiVersionKind::None:
assert(OldMVType == MultiVersionKind::TargetClones &&
"Only target_clones can be omitted in subsequent declarations");
break;
case MultiVersionKind::Target: {
const auto *CurTA = CurFD->getAttr<TargetAttr>(); const auto *CurTA = CurFD->getAttr<TargetAttr>();
if (CurTA->getFeaturesStr() == NewTA->getFeaturesStr()) { if (CurTA->getFeaturesStr() == NewTA->getFeaturesStr()) {
NewFD->setIsMultiVersion(); NewFD->setIsMultiVersion();
@ -10629,7 +10644,30 @@ static bool CheckMultiVersionAdditionalDecl(
NewFD->setInvalidDecl(); NewFD->setInvalidDecl();
return true; return true;
} }
} else { break;
}
case MultiVersionKind::TargetClones: {
const auto *CurClones = CurFD->getAttr<TargetClonesAttr>();
Redeclaration = true;
OldDecl = CurFD;
MergeTypeWithPrevious = true;
NewFD->setIsMultiVersion();
if (CurClones && NewClones &&
(CurClones->featuresStrs_size() != NewClones->featuresStrs_size() ||
!std::equal(CurClones->featuresStrs_begin(),
CurClones->featuresStrs_end(),
NewClones->featuresStrs_begin()))) {
S.Diag(NewFD->getLocation(), diag::err_target_clone_doesnt_match);
S.Diag(CurFD->getLocation(), diag::note_previous_declaration);
NewFD->setInvalidDecl();
return true;
}
return false;
}
case MultiVersionKind::CPUSpecific:
case MultiVersionKind::CPUDispatch: {
const auto *CurCPUSpec = CurFD->getAttr<CPUSpecificAttr>(); const auto *CurCPUSpec = CurFD->getAttr<CPUSpecificAttr>();
const auto *CurCPUDisp = CurFD->getAttr<CPUDispatchAttr>(); const auto *CurCPUDisp = CurFD->getAttr<CPUDispatchAttr>();
// Handle CPUDispatch/CPUSpecific versions. // Handle CPUDispatch/CPUSpecific versions.
@ -10684,8 +10722,8 @@ static bool CheckMultiVersionAdditionalDecl(
} }
} }
} }
// If the two decls aren't the same MVType, there is no possible error break;
// condition. }
} }
} }
@ -10721,7 +10759,6 @@ static bool CheckMultiVersionAdditionalDecl(
return false; return false;
} }
/// Check the validity of a mulitversion function declaration. /// Check the validity of a mulitversion function declaration.
/// Also sets the multiversion'ness' of the function itself. /// Also sets the multiversion'ness' of the function itself.
/// ///
@ -10735,23 +10772,14 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD,
const auto *NewTA = NewFD->getAttr<TargetAttr>(); const auto *NewTA = NewFD->getAttr<TargetAttr>();
const auto *NewCPUDisp = NewFD->getAttr<CPUDispatchAttr>(); const auto *NewCPUDisp = NewFD->getAttr<CPUDispatchAttr>();
const auto *NewCPUSpec = NewFD->getAttr<CPUSpecificAttr>(); const auto *NewCPUSpec = NewFD->getAttr<CPUSpecificAttr>();
const auto *NewClones = NewFD->getAttr<TargetClonesAttr>();
// Mixing Multiversioning types is prohibited. MultiVersionKind MVType = NewFD->getMultiVersionKind();
if ((NewTA && NewCPUDisp) || (NewTA && NewCPUSpec) ||
(NewCPUDisp && NewCPUSpec)) {
S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed);
NewFD->setInvalidDecl();
return true;
}
MultiVersionKind MVType = NewFD->getMultiVersionKind();
// Main isn't allowed to become a multiversion function, however it IS // Main isn't allowed to become a multiversion function, however it IS
// permitted to have 'main' be marked with the 'target' optimization hint. // permitted to have 'main' be marked with the 'target' optimization hint.
if (NewFD->isMain()) { if (NewFD->isMain()) {
if ((MVType == MultiVersionKind::Target && NewTA->isDefaultVersion()) || if (MVType != MultiVersionKind::None &&
MVType == MultiVersionKind::CPUDispatch || !(MVType == MultiVersionKind::Target && !NewTA->isDefaultVersion())) {
MVType == MultiVersionKind::CPUSpecific) {
S.Diag(NewFD->getLocation(), diag::err_multiversion_not_allowed_on_main); S.Diag(NewFD->getLocation(), diag::err_multiversion_not_allowed_on_main);
NewFD->setInvalidDecl(); NewFD->setInvalidDecl();
return true; return true;
@ -10774,13 +10802,35 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD,
if (!OldFD->isMultiVersion() && MVType == MultiVersionKind::None) if (!OldFD->isMultiVersion() && MVType == MultiVersionKind::None)
return false; return false;
if (OldFD->isMultiVersion() && MVType == MultiVersionKind::None) { // Multiversioned redeclarations aren't allowed to omit the attribute, except
// for target_clones.
if (OldFD->isMultiVersion() && MVType == MultiVersionKind::None &&
OldFD->getMultiVersionKind() != MultiVersionKind::TargetClones) {
S.Diag(NewFD->getLocation(), diag::err_multiversion_required_in_redecl) S.Diag(NewFD->getLocation(), diag::err_multiversion_required_in_redecl)
<< (OldFD->getMultiVersionKind() != MultiVersionKind::Target); << (OldFD->getMultiVersionKind() != MultiVersionKind::Target);
NewFD->setInvalidDecl(); NewFD->setInvalidDecl();
return true; return true;
} }
if (!OldFD->isMultiVersion()) {
switch (MVType) {
case MultiVersionKind::Target:
return CheckTargetCausesMultiVersioning(S, OldFD, NewFD, NewTA,
Redeclaration, OldDecl,
MergeTypeWithPrevious, Previous);
case MultiVersionKind::TargetClones:
if (OldFD->isUsed(false)) {
NewFD->setInvalidDecl();
return S.Diag(NewFD->getLocation(), diag::err_multiversion_after_used);
}
OldFD->setIsMultiVersion();
break;
case MultiVersionKind::CPUDispatch:
case MultiVersionKind::CPUSpecific:
case MultiVersionKind::None:
break;
}
}
// Handle the target potentially causes multiversioning case. // Handle the target potentially causes multiversioning case.
if (!OldFD->isMultiVersion() && MVType == MultiVersionKind::Target) if (!OldFD->isMultiVersion() && MVType == MultiVersionKind::Target)
return CheckTargetCausesMultiVersioning(S, OldFD, NewFD, NewTA, return CheckTargetCausesMultiVersioning(S, OldFD, NewFD, NewTA,
@ -10791,8 +10841,8 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD,
// appropriate attribute in the current function decl. Resolve that these are // appropriate attribute in the current function decl. Resolve that these are
// still compatible with previous declarations. // still compatible with previous declarations.
return CheckMultiVersionAdditionalDecl( return CheckMultiVersionAdditionalDecl(
S, OldFD, NewFD, MVType, NewTA, NewCPUDisp, NewCPUSpec, Redeclaration, S, OldFD, NewFD, MVType, NewTA, NewCPUDisp, NewCPUSpec, NewClones,
OldDecl, MergeTypeWithPrevious, Previous); Redeclaration, OldDecl, MergeTypeWithPrevious, Previous);
} }
/// Perform semantic checking of a new function declaration. /// Perform semantic checking of a new function declaration.

View File

@ -1965,6 +1965,28 @@ static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
} }
static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Ensure we don't combine these with themselves, since that causes some
// confusing behavior.
if (AL.getParsedKind() == ParsedAttr::AT_CPUDispatch) {
if (checkAttrMutualExclusion<CPUSpecificAttr>(S, D, AL))
return;
if (const auto *Other = D->getAttr<CPUDispatchAttr>()) {
S.Diag(AL.getLoc(), diag::err_disallowed_duplicate_attribute) << AL;
S.Diag(Other->getLocation(), diag::note_conflicting_attribute);
return;
}
} else if (AL.getParsedKind() == ParsedAttr::AT_CPUSpecific) {
if (checkAttrMutualExclusion<CPUDispatchAttr>(S, D, AL))
return;
if (const auto *Other = D->getAttr<CPUSpecificAttr>()) {
S.Diag(AL.getLoc(), diag::err_disallowed_duplicate_attribute) << AL;
S.Diag(Other->getLocation(), diag::note_conflicting_attribute);
return;
}
}
FunctionDecl *FD = cast<FunctionDecl>(D); FunctionDecl *FD = cast<FunctionDecl>(D);
if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
@ -3211,54 +3233,57 @@ static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
enum FirstParam { Unsupported, Duplicate, Unknown }; enum FirstParam { Unsupported, Duplicate, Unknown };
enum SecondParam { None, Architecture, Tune }; enum SecondParam { None, Architecture, Tune };
enum ThirdParam { Target, TargetClones };
if (AttrStr.contains("fpmath=")) if (AttrStr.contains("fpmath="))
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << "fpmath="; << Unsupported << None << "fpmath=" << Target;
// Diagnose use of tune if target doesn't support it. // Diagnose use of tune if target doesn't support it.
if (!Context.getTargetInfo().supportsTargetAttributeTune() && if (!Context.getTargetInfo().supportsTargetAttributeTune() &&
AttrStr.contains("tune=")) AttrStr.contains("tune="))
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << "tune="; << Unsupported << None << "tune=" << Target;
ParsedTargetAttr ParsedAttrs = TargetAttr::parse(AttrStr); ParsedTargetAttr ParsedAttrs = TargetAttr::parse(AttrStr);
if (!ParsedAttrs.Architecture.empty() && if (!ParsedAttrs.Architecture.empty() &&
!Context.getTargetInfo().isValidCPUName(ParsedAttrs.Architecture)) !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Architecture))
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unknown << Architecture << ParsedAttrs.Architecture; << Unknown << Architecture << ParsedAttrs.Architecture << Target;
if (!ParsedAttrs.Tune.empty() && if (!ParsedAttrs.Tune.empty() &&
!Context.getTargetInfo().isValidCPUName(ParsedAttrs.Tune)) !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Tune))
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unknown << Tune << ParsedAttrs.Tune; << Unknown << Tune << ParsedAttrs.Tune << Target;
if (ParsedAttrs.DuplicateArchitecture) if (ParsedAttrs.DuplicateArchitecture)
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Duplicate << None << "arch="; << Duplicate << None << "arch=" << Target;
if (ParsedAttrs.DuplicateTune) if (ParsedAttrs.DuplicateTune)
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Duplicate << None << "tune="; << Duplicate << None << "tune=" << Target;
for (const auto &Feature : ParsedAttrs.Features) { for (const auto &Feature : ParsedAttrs.Features) {
auto CurFeature = StringRef(Feature).drop_front(); // remove + or -. auto CurFeature = StringRef(Feature).drop_front(); // remove + or -.
if (!Context.getTargetInfo().isValidFeatureName(CurFeature)) if (!Context.getTargetInfo().isValidFeatureName(CurFeature))
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << CurFeature; << Unsupported << None << CurFeature << Target;
} }
TargetInfo::BranchProtectionInfo BPI; TargetInfo::BranchProtectionInfo BPI;
StringRef Error; StringRef DiagMsg;
if (!ParsedAttrs.BranchProtection.empty() && if (ParsedAttrs.BranchProtection.empty())
!Context.getTargetInfo().validateBranchProtection( return false;
ParsedAttrs.BranchProtection, BPI, Error)) { if (!Context.getTargetInfo().validateBranchProtection(
if (Error.empty()) ParsedAttrs.BranchProtection, BPI, DiagMsg)) {
if (DiagMsg.empty())
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << "branch-protection"; << Unsupported << None << "branch-protection" << Target;
else return Diag(LiteralLoc, diag::err_invalid_branch_protection_spec)
return Diag(LiteralLoc, diag::err_invalid_branch_protection_spec) << DiagMsg;
<< Error;
} }
if (!DiagMsg.empty())
Diag(LiteralLoc, diag::warn_unsupported_branch_protection_spec) << DiagMsg;
return false; return false;
} }
@ -3274,6 +3299,107 @@ static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(NewAttr); D->addAttr(NewAttr);
} }
bool Sema::checkTargetClonesAttrString(SourceLocation LiteralLoc, StringRef Str,
const StringLiteral *Literal,
bool &HasDefault, bool &HasCommas,
SmallVectorImpl<StringRef> &Strings) {
enum FirstParam { Unsupported, Duplicate, Unknown };
enum SecondParam { None, Architecture, Tune };
enum ThirdParam { Target, TargetClones };
HasCommas = HasCommas || Str.contains(',');
// Warn on empty at the beginning of a string.
if (Str.size() == 0)
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << "" << TargetClones;
std::pair<StringRef, StringRef> Parts = {{}, Str};
while (!Parts.second.empty()) {
Parts = Parts.second.split(',');
StringRef Cur = Parts.first.trim();
SourceLocation CurLoc = Literal->getLocationOfByte(
Cur.data() - Literal->getString().data(), getSourceManager(),
getLangOpts(), Context.getTargetInfo());
bool DefaultIsDupe = false;
if (Cur.empty())
return Diag(CurLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << "" << TargetClones;
if (Cur.startswith("arch=")) {
if (!Context.getTargetInfo().isValidCPUName(
Cur.drop_front(sizeof("arch=") - 1)))
return Diag(CurLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << Architecture
<< Cur.drop_front(sizeof("arch=") - 1) << TargetClones;
} else if (Cur == "default") {
DefaultIsDupe = HasDefault;
HasDefault = true;
} else if (!Context.getTargetInfo().isValidFeatureName(Cur))
return Diag(CurLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << Cur << TargetClones;
if (llvm::find(Strings, Cur) != Strings.end() || DefaultIsDupe)
Diag(CurLoc, diag::warn_target_clone_duplicate_options);
// Note: Add even if there are duplicates, since it changes name mangling.
Strings.push_back(Cur);
}
if (Str.rtrim().endswith(","))
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << "" << TargetClones;
return false;
}
static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Ensure we don't combine these with themselves, since that causes some
// confusing behavior.
if (const auto *Other = D->getAttr<TargetClonesAttr>()) {
S.Diag(AL.getLoc(), diag::err_disallowed_duplicate_attribute) << AL;
S.Diag(Other->getLocation(), diag::note_conflicting_attribute);
return;
}
if (checkAttrMutualExclusion<TargetClonesAttr>(S, D, AL))
return;
SmallVector<StringRef, 2> Strings;
bool HasCommas = false, HasDefault = false;
for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
StringRef CurStr;
SourceLocation LiteralLoc;
if (!S.checkStringLiteralArgumentAttr(AL, I, CurStr, &LiteralLoc) ||
S.checkTargetClonesAttrString(
LiteralLoc, CurStr,
cast<StringLiteral>(AL.getArgAsExpr(I)->IgnoreParenCasts()),
HasDefault, HasCommas, Strings))
return;
}
if (HasCommas && AL.getNumArgs() > 1)
S.Diag(AL.getLoc(), diag::warn_target_clone_mixed_values);
if (!HasDefault) {
S.Diag(AL.getLoc(), diag::err_target_clone_must_have_default);
return;
}
// FIXME: We could probably figure out how to get this to work for lambdas
// someday.
if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
if (MD->getParent()->isLambda()) {
S.Diag(D->getLocation(), diag::err_multiversion_doesnt_support)
<< static_cast<unsigned>(MultiVersionKind::TargetClones)
<< /*Lambda*/ 9;
return;
}
}
cast<FunctionDecl>(D)->setIsMultiVersion();
TargetClonesAttr *NewAttr = ::new (S.Context)
TargetClonesAttr(S.Context, AL, Strings.data(), Strings.size());
D->addAttr(NewAttr);
}
static void handleMinVectorWidthAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleMinVectorWidthAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
Expr *E = AL.getArgAsExpr(0); Expr *E = AL.getArgAsExpr(0);
uint32_t VecWidth; uint32_t VecWidth;
@ -8217,6 +8343,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_Target: case ParsedAttr::AT_Target:
handleTargetAttr(S, D, AL); handleTargetAttr(S, D, AL);
break; break;
case ParsedAttr::AT_TargetClones:
handleTargetClonesAttr(S, D, AL);
break;
case ParsedAttr::AT_MinVectorWidth: case ParsedAttr::AT_MinVectorWidth:
handleMinVectorWidthAttr(S, D, AL); handleMinVectorWidthAttr(S, D, AL);
break; break;

View File

@ -16566,6 +16566,17 @@ Sema::PushExpressionEvaluationContext(
ExpressionEvaluationContextRecord::ExpressionKind ExprContext) { ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup, ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup,
LambdaContextDecl, ExprContext); LambdaContextDecl, ExprContext);
// Discarded statements and immediate contexts nested in other
// discarded statements or immediate context are themselves
// a discarded statement or an immediate context, respectively.
ExprEvalContexts.back().InDiscardedStatement =
ExprEvalContexts[ExprEvalContexts.size() - 2]
.isDiscardedStatementContext();
ExprEvalContexts.back().InImmediateFunctionContext =
ExprEvalContexts[ExprEvalContexts.size() - 2]
.isImmediateFunctionContext();
Cleanup.reset(); Cleanup.reset();
if (!MaybeODRUseExprs.empty()) if (!MaybeODRUseExprs.empty())
std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs); std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
@ -18965,6 +18976,10 @@ bool Sema::DiagIfReachable(SourceLocation Loc, ArrayRef<const Stmt *> Stmts,
/// during overload resolution or within sizeof/alignof/typeof/typeid. /// during overload resolution or within sizeof/alignof/typeof/typeid.
bool Sema::DiagRuntimeBehavior(SourceLocation Loc, ArrayRef<const Stmt*> Stmts, bool Sema::DiagRuntimeBehavior(SourceLocation Loc, ArrayRef<const Stmt*> Stmts,
const PartialDiagnostic &PD) { const PartialDiagnostic &PD) {
if (ExprEvalContexts.back().isDiscardedStatementContext())
return false;
switch (ExprEvalContexts.back().Context) { switch (ExprEvalContexts.back().Context) {
case ExpressionEvaluationContext::Unevaluated: case ExpressionEvaluationContext::Unevaluated:
case ExpressionEvaluationContext::UnevaluatedList: case ExpressionEvaluationContext::UnevaluatedList:

View File

@ -1508,8 +1508,9 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
} }
// Only construct objects with object types. // Only construct objects with object types.
// There doesn't seem to be an explicit rule for this but functions are // The standard doesn't explicitly forbid function types here, but that's an
// not objects, so they cannot take initializers. // obvious oversight, as there's no way to dynamically construct a function
// in general.
if (Ty->isFunctionType()) if (Ty->isFunctionType())
return ExprError(Diag(TyBeginLoc, diag::err_init_for_function_type) return ExprError(Diag(TyBeginLoc, diag::err_init_for_function_type)
<< Ty << FullRange); << Ty << FullRange);

View File

@ -3563,8 +3563,7 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
bool HasDeducedReturnType = bool HasDeducedReturnType =
CurLambda && hasDeducedReturnType(CurLambda->CallOperator); CurLambda && hasDeducedReturnType(CurLambda->CallOperator);
if (ExprEvalContexts.back().Context == if (ExprEvalContexts.back().isDiscardedStatementContext() &&
ExpressionEvaluationContext::DiscardedStatement &&
(HasDeducedReturnType || CurCap->HasImplicitReturnType)) { (HasDeducedReturnType || CurCap->HasImplicitReturnType)) {
if (RetValExp) { if (RetValExp) {
ExprResult ER = ExprResult ER =
@ -3880,8 +3879,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
if (RetVal.isInvalid()) if (RetVal.isInvalid())
return StmtError(); return StmtError();
StmtResult R = BuildReturnStmt(ReturnLoc, RetVal.get()); StmtResult R = BuildReturnStmt(ReturnLoc, RetVal.get());
if (R.isInvalid() || ExprEvalContexts.back().Context == if (R.isInvalid() || ExprEvalContexts.back().isDiscardedStatementContext())
ExpressionEvaluationContext::DiscardedStatement)
return R; return R;
if (VarDecl *VD = if (VarDecl *VD =
@ -3966,8 +3964,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// C++1z: discarded return statements are not considered when deducing a // C++1z: discarded return statements are not considered when deducing a
// return type. // return type.
if (ExprEvalContexts.back().Context == if (ExprEvalContexts.back().isDiscardedStatementContext() &&
ExpressionEvaluationContext::DiscardedStatement &&
FnRetType->getContainedAutoType()) { FnRetType->getContainedAutoType()) {
if (RetValExp) { if (RetValExp) {
ExprResult ER = ExprResult ER =

View File

@ -686,8 +686,8 @@ SwitchNodeBuilder::generateDefaultCaseNode(ProgramStateRef St,
assert(Src->succ_rbegin() != Src->succ_rend()); assert(Src->succ_rbegin() != Src->succ_rend());
CFGBlock *DefaultBlock = *Src->succ_rbegin(); CFGBlock *DefaultBlock = *Src->succ_rbegin();
// Sanity check for default blocks that are unreachable and not caught // Basic correctness check for default blocks that are unreachable and not
// by earlier stages. // caught by earlier stages.
if (!DefaultBlock) if (!DefaultBlock)
return nullptr; return nullptr;

View File

@ -2191,6 +2191,42 @@ LLVM_NODISCARD ProgramStateRef reAssume(ProgramStateRef State,
Constraint->getMaxValue(), true); Constraint->getMaxValue(), true);
} }
// Simplify the given symbol with the help of the SValBuilder. In
// SValBuilder::symplifySval, we traverse the symbol tree and query the
// constraint values for the sub-trees and if a value is a constant we do the
// constant folding. Compound symbols might collapse to simpler symbol tree
// that is still possible to further simplify. Thus, we do the simplification on
// a new symbol tree until we reach the simplest form, i.e. the fixpoint.
//
// Consider the following symbol `(b * b) * b * b` which has this tree:
// *
// / \
// * b
// / \
// / b
// (b * b)
// Now, if the `b * b == 1` new constraint is added then during the first
// iteration we have the following transformations:
// * *
// / \ / \
// * b --> b b
// / \
// / b
// 1
// We need another iteration to reach the final result `1`.
LLVM_NODISCARD
static SVal simplifyUntilFixpoint(SValBuilder &SVB, ProgramStateRef State,
const SymbolRef Sym) {
SVal Val = SVB.makeSymbolVal(Sym);
SVal SimplifiedVal = SVB.simplifySVal(State, Val);
// Do the simplification until we can.
while (SimplifiedVal != Val) {
Val = SimplifiedVal;
SimplifiedVal = SVB.simplifySVal(State, Val);
}
return SimplifiedVal;
}
// Iterate over all symbols and try to simplify them. Once a symbol is // Iterate over all symbols and try to simplify them. Once a symbol is
// simplified then we check if we can merge the simplified symbol's equivalence // simplified then we check if we can merge the simplified symbol's equivalence
// class to this class. This way, we simplify not just the symbols but the // class to this class. This way, we simplify not just the symbols but the
@ -2202,7 +2238,8 @@ EquivalenceClass::simplify(SValBuilder &SVB, RangeSet::Factory &F,
SymbolSet ClassMembers = Class.getClassMembers(State); SymbolSet ClassMembers = Class.getClassMembers(State);
for (const SymbolRef &MemberSym : ClassMembers) { for (const SymbolRef &MemberSym : ClassMembers) {
const SVal SimplifiedMemberVal = simplifyToSVal(State, MemberSym); const SVal SimplifiedMemberVal =
simplifyUntilFixpoint(SVB, State, MemberSym);
const SymbolRef SimplifiedMemberSym = SimplifiedMemberVal.getAsSymbol(); const SymbolRef SimplifiedMemberSym = SimplifiedMemberVal.getAsSymbol();
// The symbol is collapsed to a constant, check if the current State is // The symbol is collapsed to a constant, check if the current State is

View File

@ -372,6 +372,15 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
NonLoc InputLHS = lhs; NonLoc InputLHS = lhs;
NonLoc InputRHS = rhs; NonLoc InputRHS = rhs;
// Constraints may have changed since the creation of a bound SVal. Check if
// the values can be simplified based on those new constraints.
SVal simplifiedLhs = simplifySVal(state, lhs);
SVal simplifiedRhs = simplifySVal(state, rhs);
if (auto simplifiedLhsAsNonLoc = simplifiedLhs.getAs<NonLoc>())
lhs = *simplifiedLhsAsNonLoc;
if (auto simplifiedRhsAsNonLoc = simplifiedRhs.getAs<NonLoc>())
rhs = *simplifiedRhsAsNonLoc;
// Handle trivial case where left-side and right-side are the same. // Handle trivial case where left-side and right-side are the same.
if (lhs == rhs) if (lhs == rhs)
switch (op) { switch (op) {
@ -619,16 +628,6 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
} }
} }
// Does the symbolic expression simplify to a constant?
// If so, "fold" the constant by setting 'lhs' to a ConcreteInt
// and try again.
SVal simplifiedLhs = simplifySVal(state, lhs);
if (simplifiedLhs != lhs)
if (auto simplifiedLhsAsNonLoc = simplifiedLhs.getAs<NonLoc>()) {
lhs = *simplifiedLhsAsNonLoc;
continue;
}
// Is the RHS a constant? // Is the RHS a constant?
if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs)) if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs))
return MakeSymIntVal(Sym, op, *RHSValue, resultTy); return MakeSymIntVal(Sym, op, *RHSValue, resultTy);
@ -1103,7 +1102,6 @@ const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,
if (SymbolRef Sym = V.getAsSymbol()) if (SymbolRef Sym = V.getAsSymbol())
return state->getConstraintManager().getSymVal(state, Sym); return state->getConstraintManager().getSymVal(state, Sym);
// FIXME: Add support for SymExprs.
return nullptr; return nullptr;
} }
@ -1135,6 +1133,24 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
return cache(Sym, SVB.makeSymbolVal(Sym)); return cache(Sym, SVB.makeSymbolVal(Sym));
} }
// Return the known const value for the Sym if available, or return Undef
// otherwise.
SVal getConst(SymbolRef Sym) {
const llvm::APSInt *Const =
State->getConstraintManager().getSymVal(State, Sym);
if (Const)
return Loc::isLocType(Sym->getType()) ? (SVal)SVB.makeIntLocVal(*Const)
: (SVal)SVB.makeIntVal(*Const);
return UndefinedVal();
}
SVal getConstOrVisit(SymbolRef Sym) {
const SVal Ret = getConst(Sym);
if (Ret.isUndef())
return Visit(Sym);
return Ret;
}
public: public:
Simplifier(ProgramStateRef State) Simplifier(ProgramStateRef State)
: State(State), SVB(State->getStateManager().getSValBuilder()) {} : State(State), SVB(State->getStateManager().getSValBuilder()) {}
@ -1148,15 +1164,14 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
return SVB.makeSymbolVal(S); return SVB.makeSymbolVal(S);
} }
// TODO: Support SymbolCast. Support IntSymExpr when/if we actually // TODO: Support SymbolCast.
// start producing them.
SVal VisitSymIntExpr(const SymIntExpr *S) { SVal VisitSymIntExpr(const SymIntExpr *S) {
auto I = Cached.find(S); auto I = Cached.find(S);
if (I != Cached.end()) if (I != Cached.end())
return I->second; return I->second;
SVal LHS = Visit(S->getLHS()); SVal LHS = getConstOrVisit(S->getLHS());
if (isUnchanged(S->getLHS(), LHS)) if (isUnchanged(S->getLHS(), LHS))
return skip(S); return skip(S);
@ -1183,6 +1198,20 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
S, SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType())); S, SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType()));
} }
SVal VisitIntSymExpr(const IntSymExpr *S) {
auto I = Cached.find(S);
if (I != Cached.end())
return I->second;
SVal RHS = getConstOrVisit(S->getRHS());
if (isUnchanged(S->getRHS(), RHS))
return skip(S);
SVal LHS = SVB.makeIntVal(S->getLHS());
return cache(
S, SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType()));
}
SVal VisitSymSymExpr(const SymSymExpr *S) { SVal VisitSymSymExpr(const SymSymExpr *S) {
auto I = Cached.find(S); auto I = Cached.find(S);
if (I != Cached.end()) if (I != Cached.end())
@ -1196,8 +1225,9 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
Loc::isLocType(S->getRHS()->getType())) Loc::isLocType(S->getRHS()->getType()))
return skip(S); return skip(S);
SVal LHS = Visit(S->getLHS()); SVal LHS = getConstOrVisit(S->getLHS());
SVal RHS = Visit(S->getRHS()); SVal RHS = getConstOrVisit(S->getRHS());
if (isUnchanged(S->getLHS(), LHS) && isUnchanged(S->getRHS(), RHS)) if (isUnchanged(S->getLHS(), LHS) && isUnchanged(S->getRHS(), RHS))
return skip(S); return skip(S);

View File

@ -591,16 +591,24 @@ AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
// - Main source file: run both path-sensitive and non-path-sensitive checks. // - Main source file: run both path-sensitive and non-path-sensitive checks.
// - Header files: run non-path-sensitive checks only. // - Header files: run non-path-sensitive checks only.
// - System headers: don't run any checks. // - System headers: don't run any checks.
SourceManager &SM = Ctx->getSourceManager(); if (Opts->AnalyzeAll)
const Stmt *Body = D->getBody(); return Mode;
SourceLocation SL = Body ? Body->getBeginLoc() : D->getLocation();
SL = SM.getExpansionLoc(SL);
if (!Opts->AnalyzeAll && !Mgr->isInCodeFile(SL)) { const SourceManager &SM = Ctx->getSourceManager();
if (SL.isInvalid() || SM.isInSystemHeader(SL))
return AM_None; const SourceLocation Loc = [&SM](Decl *D) -> SourceLocation {
const Stmt *Body = D->getBody();
SourceLocation SL = Body ? Body->getBeginLoc() : D->getLocation();
return SM.getExpansionLoc(SL);
}(D);
// Ignore system headers.
if (Loc.isInvalid() || SM.isInSystemHeader(Loc))
return AM_None;
// Disable path sensitive analysis in user-headers.
if (!Mgr->isInCodeFile(Loc))
return Mode & ~AM_Path; return Mode & ~AM_Path;
}
return Mode; return Mode;
} }

View File

@ -129,7 +129,7 @@ DependencyScanningFilesystemSharedCache::get(StringRef Key, bool Minimized) {
/// ///
/// This is kinda hacky, it would be better if we knew what kind of file Clang /// This is kinda hacky, it would be better if we knew what kind of file Clang
/// was expecting instead. /// was expecting instead.
static bool shouldMinimize(StringRef Filename) { static bool shouldMinimizeBasedOnExtension(StringRef Filename) {
StringRef Ext = llvm::sys::path::extension(Filename); StringRef Ext = llvm::sys::path::extension(Filename);
if (Ext.empty()) if (Ext.empty())
return true; // C++ standard library return true; // C++ standard library
@ -147,26 +147,43 @@ static bool shouldCacheStatFailures(StringRef Filename) {
StringRef Ext = llvm::sys::path::extension(Filename); StringRef Ext = llvm::sys::path::extension(Filename);
if (Ext.empty()) if (Ext.empty())
return false; // This may be the module cache directory. return false; // This may be the module cache directory.
return shouldMinimize(Filename); // Only cache stat failures on source files. // Only cache stat failures on source files.
return shouldMinimizeBasedOnExtension(Filename);
} }
void DependencyScanningWorkerFilesystem::ignoreFile(StringRef RawFilename) { void DependencyScanningWorkerFilesystem::disableMinimization(
llvm::SmallString<256> Filename;
llvm::sys::path::native(RawFilename, Filename);
IgnoredFiles.insert(Filename);
}
bool DependencyScanningWorkerFilesystem::shouldIgnoreFile(
StringRef RawFilename) { StringRef RawFilename) {
llvm::SmallString<256> Filename; llvm::SmallString<256> Filename;
llvm::sys::path::native(RawFilename, Filename); llvm::sys::path::native(RawFilename, Filename);
return IgnoredFiles.contains(Filename); NotToBeMinimized.insert(Filename);
}
bool DependencyScanningWorkerFilesystem::shouldMinimize(StringRef RawFilename) {
if (!shouldMinimizeBasedOnExtension(RawFilename))
return false;
llvm::SmallString<256> Filename;
llvm::sys::path::native(RawFilename, Filename);
return !NotToBeMinimized.contains(Filename);
}
CachedFileSystemEntry DependencyScanningWorkerFilesystem::createFileSystemEntry(
llvm::ErrorOr<llvm::vfs::Status> &&MaybeStatus, StringRef Filename,
bool ShouldMinimize) {
if (!MaybeStatus)
return CachedFileSystemEntry(MaybeStatus.getError());
if (MaybeStatus->isDirectory())
return CachedFileSystemEntry::createDirectoryEntry(std::move(*MaybeStatus));
return CachedFileSystemEntry::createFileEntry(Filename, getUnderlyingFS(),
ShouldMinimize);
} }
llvm::ErrorOr<const CachedFileSystemEntry *> llvm::ErrorOr<const CachedFileSystemEntry *>
DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry( DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry(
const StringRef Filename) { const StringRef Filename) {
bool ShouldMinimize = !shouldIgnoreFile(Filename) && shouldMinimize(Filename); bool ShouldMinimize = shouldMinimize(Filename);
if (const auto *Entry = Cache.getCachedEntry(Filename, ShouldMinimize)) if (const auto *Entry = Cache.getCachedEntry(Filename, ShouldMinimize))
return Entry; return Entry;
@ -182,23 +199,15 @@ DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry(
CachedFileSystemEntry &CacheEntry = SharedCacheEntry.Value; CachedFileSystemEntry &CacheEntry = SharedCacheEntry.Value;
if (!CacheEntry.isValid()) { if (!CacheEntry.isValid()) {
llvm::vfs::FileSystem &FS = getUnderlyingFS(); auto MaybeStatus = getUnderlyingFS().status(Filename);
auto MaybeStatus = FS.status(Filename); if (!MaybeStatus && !shouldCacheStatFailures(Filename))
if (!MaybeStatus) { // HACK: We need to always restat non source files if the stat fails.
if (!shouldCacheStatFailures(Filename)) // This is because Clang first looks up the module cache and module
// HACK: We need to always restat non source files if the stat fails. // files before building them, and then looks for them again. If we
// This is because Clang first looks up the module cache and module // cache the stat failure, it won't see them the second time.
// files before building them, and then looks for them again. If we return MaybeStatus.getError();
// cache the stat failure, it won't see them the second time. CacheEntry = createFileSystemEntry(std::move(MaybeStatus), Filename,
return MaybeStatus.getError(); ShouldMinimize);
else
CacheEntry = CachedFileSystemEntry(MaybeStatus.getError());
} else if (MaybeStatus->isDirectory())
CacheEntry = CachedFileSystemEntry::createDirectoryEntry(
std::move(*MaybeStatus));
else
CacheEntry = CachedFileSystemEntry::createFileEntry(Filename, FS,
ShouldMinimize);
} }
Result = &CacheEntry; Result = &CacheEntry;

View File

@ -193,20 +193,19 @@ class DependencyScanningAction : public tooling::ToolAction {
// Use the dependency scanning optimized file system if requested to do so. // Use the dependency scanning optimized file system if requested to do so.
if (DepFS) { if (DepFS) {
DepFS->clearIgnoredFiles(); DepFS->enableMinimizationOfAllFiles();
// Ignore any files that contributed to prebuilt modules. The implicit // Don't minimize any files that contributed to prebuilt modules. The
// build validates the modules by comparing the reported sizes of their // implicit build validates the modules by comparing the reported sizes of
// inputs to the current state of the filesystem. Minimization would throw // their inputs to the current state of the filesystem. Minimization would
// this mechanism off. // throw this mechanism off.
for (const auto &File : PrebuiltModulesInputFiles) for (const auto &File : PrebuiltModulesInputFiles)
DepFS->ignoreFile(File.getKey()); DepFS->disableMinimization(File.getKey());
// Add any filenames that were explicity passed in the build settings and // Don't minimize any files that were explicitly passed in the build
// that might be opened, as we want to ensure we don't run source // settings and that might be opened.
// minimization on them.
for (const auto &E : ScanInstance.getHeaderSearchOpts().UserEntries) for (const auto &E : ScanInstance.getHeaderSearchOpts().UserEntries)
DepFS->ignoreFile(E.Path); DepFS->disableMinimization(E.Path);
for (const auto &F : ScanInstance.getHeaderSearchOpts().VFSOverlayFiles) for (const auto &F : ScanInstance.getHeaderSearchOpts().VFSOverlayFiles)
DepFS->ignoreFile(F); DepFS->disableMinimization(F);
// Support for virtual file system overlays on top of the caching // Support for virtual file system overlays on top of the caching
// filesystem. // filesystem.

View File

@ -107,7 +107,7 @@ static void visitASTNodeRecursive(ASTNode node, ASTNode base,
static void visitHierarchy(RecordKeeper &records, static void visitHierarchy(RecordKeeper &records,
StringRef nodeClassName, StringRef nodeClassName,
ASTNodeHierarchyVisitor<ASTNode> visit) { ASTNodeHierarchyVisitor<ASTNode> visit) {
// Check for the node class, just as a sanity check. // Check for the node class, just as a basic correctness check.
if (!records.getClass(nodeClassName)) { if (!records.getClass(nodeClassName)) {
PrintFatalError(Twine("cannot find definition for node class ") PrintFatalError(Twine("cannot find definition for node class ")
+ nodeClassName); + nodeClassName);

View File

@ -0,0 +1,61 @@
#ifndef MEMPROF_DATA_INC
#define MEMPROF_DATA_INC
/*===-- MemProfData.inc - MemProf profiling runtime structures -*- 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 is the main file that defines all the data structure, signature,
* constant literals that are shared across profiling runtime library,
* and host tools (reader/writer).
*
* This file has two identical copies. The primary copy lives in LLVM and
* the other one sits in compiler-rt/include/profile directory. To make changes
* in this file, first modify the primary copy and copy it over to compiler-rt.
* Testing of any change in this file can start only after the two copies are
* synced up.
*
\*===----------------------------------------------------------------------===*/
#ifdef _MSC_VER
#define PACKED(__decl__) __pragma(pack(push,1)) __decl__ __pragma(pack(pop))
#else
#define PACKED(__decl__) __decl__ __attribute__((__packed__))
#endif
// A 64-bit magic number to uniquely identify the raw binary memprof profile file.
#define MEMPROF_RAW_MAGIC_64 \
((uint64_t)255 << 56 | (uint64_t)'m' << 48 | (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | \
(uint64_t)'o' << 24 | (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129)
// The version number of the raw binary format.
#define MEMPROF_RAW_VERSION 1ULL
namespace llvm {
namespace memprof {
// A struct describing the header used for the raw binary memprof profile format.
PACKED(struct Header {
uint64_t Magic;
uint64_t Version;
uint64_t TotalSize;
uint64_t SegmentOffset;
uint64_t MIBOffset;
uint64_t StackOffset;
});
// A struct describing the information necessary to describe a /proc/maps
// segment entry for a particular binary/library identified by its build id.
PACKED(struct SegmentEntry {
uint64_t Start;
uint64_t End;
uint64_t Offset;
uint8_t BuildId[32];
});
} // namespace memprof
} // namespace llvm
#endif

View File

@ -130,23 +130,24 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
// Strict init-order checking is dlopen-hostile: // Strict init-order checking is dlopen-hostile:
// https://github.com/google/sanitizers/issues/178 // https://github.com/google/sanitizers/issues/178
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \ # define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
do { \ ({ \
if (flags()->strict_init_order) \ if (flags()->strict_init_order) \
StopInitOrderChecking(); \ StopInitOrderChecking(); \
CheckNoDeepBind(filename, flag); \ CheckNoDeepBind(filename, flag); \
} while (false) REAL(dlopen)(filename, flag); \
#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() })
#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) # define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() # define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited) # define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ # define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
if (AsanThread *t = GetCurrentThread()) { \ # define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
*begin = t->tls_begin(); \ if (AsanThread *t = GetCurrentThread()) { \
*end = t->tls_end(); \ *begin = t->tls_begin(); \
} else { \ *end = t->tls_end(); \
*begin = *end = 0; \ } else { \
} *begin = *end = 0; \
}
#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \ #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
do { \ do { \

View File

@ -460,6 +460,10 @@ static bool SuppressErrorReport(uptr pc) {
void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write, void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
uptr access_size, u32 exp, bool fatal) { uptr access_size, u32 exp, bool fatal) {
if (__asan_test_only_reported_buggy_pointer) {
*__asan_test_only_reported_buggy_pointer = addr;
return;
}
if (!fatal && SuppressErrorReport(pc)) return; if (!fatal && SuppressErrorReport(pc)) return;
ENABLE_FRAME_POINTER; ENABLE_FRAME_POINTER;

View File

@ -85,12 +85,8 @@ void ShowStatsAndAbort() {
NOINLINE NOINLINE
static void ReportGenericErrorWrapper(uptr addr, bool is_write, int size, static void ReportGenericErrorWrapper(uptr addr, bool is_write, int size,
int exp_arg, bool fatal) { int exp_arg, bool fatal) {
if (__asan_test_only_reported_buggy_pointer) { GET_CALLER_PC_BP_SP;
*__asan_test_only_reported_buggy_pointer = addr; ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, fatal);
} else {
GET_CALLER_PC_BP_SP;
ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, fatal);
}
} }
// --------------- LowLevelAllocateCallbac ---------- {{{1 // --------------- LowLevelAllocateCallbac ---------- {{{1

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