Merge llvm-project main llvmorg-15-init-16436-g18a6ab5b8d1f

This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-15-init-16436-g18a6ab5b8d1f.

PR:		265425
MFC after:	2 weeks
This commit is contained in:
Dimitry Andric 2022-07-14 20:58:48 +02:00
commit 753f127f3a
1068 changed files with 27192 additions and 10481 deletions

View File

@ -76,7 +76,7 @@ class CommonEntityInfo {
}
void setSwiftPrivate(llvm::Optional<bool> Private) {
SwiftPrivateSpecified = Private.hasValue();
SwiftPrivateSpecified = Private.has_value();
SwiftPrivate = Private ? *Private : 0;
}

View File

@ -130,6 +130,7 @@ class TemplateDecl;
class TemplateParameterList;
class TemplateTemplateParmDecl;
class TemplateTypeParmDecl;
class TypeConstraint;
class UnresolvedSetIterator;
class UsingShadowDecl;
class VarTemplateDecl;
@ -260,7 +261,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<DeducedTemplateSpecializationType>
DeducedTemplateSpecializationTypes;
mutable llvm::FoldingSet<AtomicType> AtomicTypes;
llvm::FoldingSet<AttributedType> AttributedTypes;
mutable llvm::FoldingSet<AttributedType> AttributedTypes;
mutable llvm::FoldingSet<PipeType> PipeTypes;
mutable llvm::FoldingSet<BitIntType> BitIntTypes;
mutable llvm::FoldingSet<DependentBitIntType> DependentBitIntTypes;
@ -1306,11 +1307,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// declaration of a function with an exception specification is permitted
/// and preserved. Other type sugar (for instance, typedefs) is not.
QualType getFunctionTypeWithExceptionSpec(
QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI);
QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI) const;
/// Determine whether two function types are the same, ignoring
/// exception specifications in cases where they're part of the type.
bool hasSameFunctionTypeIgnoringExceptionSpec(QualType T, QualType U);
bool hasSameFunctionTypeIgnoringExceptionSpec(QualType T, QualType U) const;
/// Change the exception specification on a function once it is
/// delay-parsed, instantiated, or computed.
@ -1597,9 +1598,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;
QualType getAttributedType(attr::Kind attrKind,
QualType modifiedType,
QualType equivalentType);
QualType getAttributedType(attr::Kind attrKind, QualType modifiedType,
QualType equivalentType) const;
QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
QualType Wrapped);
@ -2654,25 +2654,33 @@ class ASTContext : public RefCountedBase<ASTContext> {
bool hasSameTemplateName(const TemplateName &X, const TemplateName &Y) const;
/// Determine whether the two declarations refer to the same entity.
///
/// FIXME: isSameEntity is not const due to its implementation calls
/// hasSameFunctionTypeIgnoringExceptionSpec which may alter this.
bool isSameEntity(const NamedDecl *X, const NamedDecl *Y);
bool isSameEntity(const NamedDecl *X, const NamedDecl *Y) const;
/// Determine whether two template parameter lists are similar enough
/// that they may be used in declarations of the same template.
///
/// FIXME: isSameTemplateParameterList is not const since it calls
/// isSameTemplateParameter.
bool isSameTemplateParameterList(const TemplateParameterList *X,
const TemplateParameterList *Y);
const TemplateParameterList *Y) const;
/// Determine whether two template parameters are similar enough
/// that they may be used in declarations of the same template.
bool isSameTemplateParameter(const NamedDecl *X, const NamedDecl *Y) const;
/// Determine whether two 'requires' expressions are similar enough that they
/// may be used in re-declarations.
///
/// FIXME: isSameTemplateParameterList is not const since it calls
/// isSameEntity.
bool isSameTemplateParameter(const NamedDecl *X, const NamedDecl *Y);
/// Use of 'requires' isn't mandatory, works with constraints expressed in
/// other ways too.
bool isSameConstraintExpr(const Expr *XCE, const Expr *YCE) const;
/// Determine whether two type contraint are similar enough that they could
/// used in declarations of the same template.
bool isSameTypeConstraint(const TypeConstraint *XTC,
const TypeConstraint *YTC) const;
/// Determine whether two default template arguments are similar enough
/// that they may be used in declarations of the same template.
bool isSameDefaultTemplateArgument(const NamedDecl *X,
const NamedDecl *Y) const;
/// Retrieve the "canonical" template argument.
///

View File

@ -19,7 +19,6 @@
namespace clang {
class ASTImportError : public llvm::ErrorInfo<ASTImportError> {
public:
/// \brief Kind of error when importing an AST component.
enum ErrorKind {

View File

@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_DECLTEMPLATE_H
#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
@ -373,11 +374,19 @@ class DefaultArgStorage {
/// Set that the default argument was inherited from another parameter.
void setInherited(const ASTContext &C, ParmDecl *InheritedFrom) {
assert(!isInherited() && "default argument already inherited");
InheritedFrom = getParmOwningDefaultArg(InheritedFrom);
if (!isSet())
ValueOrInherited = InheritedFrom;
else
else if (auto *D = ValueOrInherited.template dyn_cast<ParmDecl *>()) {
assert(C.isSameDefaultTemplateArgument(D, InheritedFrom));
ValueOrInherited =
new (allocateDefaultArgStorageChain(C)) Chain{InheritedFrom, get()};
} else if (auto *Inherited =
ValueOrInherited.template dyn_cast<Chain *>()) {
assert(C.isSameDefaultTemplateArgument(Inherited->PrevDeclWithDefaultArg,
InheritedFrom));
Inherited->PrevDeclWithDefaultArg = InheritedFrom;
} else
ValueOrInherited = new (allocateDefaultArgStorageChain(C))
Chain{InheritedFrom, ValueOrInherited.template get<ArgType>()};
}

View File

@ -520,15 +520,15 @@ let Class = PropertyTypeCase<APValue, "LValue"> in {
if (hasBase) {
if (isTypeInfo) {
base = APValue::LValueBase::getTypeInfo(
TypeInfoLValue(typeInfo.getValue().getTypePtr()), type.getValue());
TypeInfoLValue(typeInfo.value().getTypePtr()), type.value());
elemTy = base.getTypeInfoType();
} else if (isExpr) {
base = APValue::LValueBase(cast<Expr>(stmt.getValue()),
callIndex.getValue(), version.getValue());
base = APValue::LValueBase(cast<Expr>(stmt.value()),
callIndex.value(), version.value());
elemTy = base.get<const Expr *>()->getType();
} else {
base = APValue::LValueBase(cast<ValueDecl>(decl.getValue()),
callIndex.getValue(), version.getValue());
base = APValue::LValueBase(cast<ValueDecl>(decl.value()),
callIndex.value(), version.value());
elemTy = base.get<const ValueDecl *>()->getType();
}
}

View File

@ -155,6 +155,7 @@ class DataflowAnalysisContext {
/// Returns a pointer value that represents a null pointer. Calls with
/// `PointeeType` that are canonically equivalent will return the same result.
/// A null `PointeeType` can be used for the pointee of `std::nullptr_t`.
PointerValue &getOrCreateNullPointerValue(QualType PointeeType);
/// Returns a symbolic boolean value that models a boolean literal equal to
@ -251,6 +252,17 @@ class DataflowAnalysisContext {
bool equivalentBoolValues(BoolValue &Val1, BoolValue &Val2);
private:
struct NullableQualTypeDenseMapInfo : private llvm::DenseMapInfo<QualType> {
static QualType getEmptyKey() {
// Allow a NULL `QualType` by using a different value as the empty key.
return QualType::getFromOpaquePtr(reinterpret_cast<Type *>(1));
}
using DenseMapInfo::getHashValue;
using DenseMapInfo::getTombstoneKey;
using DenseMapInfo::isEqual;
};
/// Adds all constraints of the flow condition identified by `Token` and all
/// of its transitive dependencies to `Constraints`. `VisitedTokens` is used
/// to track tokens of flow conditions that were already visited by recursive
@ -259,17 +271,18 @@ class DataflowAnalysisContext {
AtomicBoolValue &Token, llvm::DenseSet<BoolValue *> &Constraints,
llvm::DenseSet<AtomicBoolValue *> &VisitedTokens);
/// Returns the result of satisfiability checking on `Constraints`.
/// Possible return values are:
/// - `Satisfiable`: There exists a satisfying assignment for `Constraints`.
/// - `Unsatisfiable`: There is no satisfying assignment for `Constraints`.
/// - `TimedOut`: The solver gives up on finding a satisfying assignment.
/// Returns the outcome of satisfiability checking on `Constraints`.
/// Possible outcomes are:
/// - `Satisfiable`: A satisfying assignment exists and is returned.
/// - `Unsatisfiable`: A satisfying assignment does not exist.
/// - `TimedOut`: The search for a satisfying assignment was not completed.
Solver::Result querySolver(llvm::DenseSet<BoolValue *> Constraints);
/// Returns true if the solver is able to prove that there is no satisfying
/// assignment for `Constraints`
bool isUnsatisfiable(llvm::DenseSet<BoolValue *> Constraints) {
return querySolver(std::move(Constraints)) == Solver::Result::Unsatisfiable;
return querySolver(std::move(Constraints)).getStatus() ==
Solver::Result::Status::Unsatisfiable;
}
/// Returns a boolean value as a result of substituting `Val` and its sub
@ -311,7 +324,8 @@ class DataflowAnalysisContext {
// required to initialize the `PointeeLoc` field in `PointerValue`. Consider
// creating a type-independent `NullPointerValue` without a `PointeeLoc`
// field.
llvm::DenseMap<QualType, PointerValue *> NullPointerVals;
llvm::DenseMap<QualType, PointerValue *, NullableQualTypeDenseMapInfo>
NullPointerVals;
AtomicBoolValue &TrueVal;
AtomicBoolValue &FalseVal;

View File

@ -0,0 +1,63 @@
//===-- DebugSupport.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 functions which generate more readable forms of data
// structures used in the dataflow analyses, for debugging purposes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DEBUGSUPPORT_H_
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DEBUGSUPPORT_H_
#include <string>
#include <vector>
#include "clang/Analysis/FlowSensitive/Solver.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseMap.h"
namespace clang {
namespace dataflow {
/// Returns a string representation for the boolean value `B`.
///
/// Atomic booleans appearing in the boolean value `B` are assigned to labels
/// either specified in `AtomNames` or created by default rules as B0, B1, ...
///
/// Requirements:
///
/// Names assigned to atoms should not be repeated in `AtomNames`.
std::string debugString(
const BoolValue &B,
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {{}});
/// Returns a string representation for `Constraints` - a collection of boolean
/// formulas and the `Result` of satisfiability checking.
///
/// Atomic booleans appearing in `Constraints` and `Result` are assigned to
/// labels either specified in `AtomNames` or created by default rules as B0,
/// B1, ...
///
/// Requirements:
///
/// Names assigned to atoms should not be repeated in `AtomNames`.
std::string debugString(
const std::vector<BoolValue *> &Constraints, const Solver::Result &Result,
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {{}});
inline std::string debugString(
const llvm::DenseSet<BoolValue *> &Constraints,
const Solver::Result &Result,
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {{}}) {
std::vector<BoolValue *> ConstraintsVec(Constraints.begin(),
Constraints.end());
return debugString(ConstraintsVec, Result, std::move(AtomNames));
}
} // namespace dataflow
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DEBUGSUPPORT_H_

View File

@ -15,7 +15,9 @@
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SOLVER_H
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
namespace clang {
namespace dataflow {
@ -23,17 +25,58 @@ namespace dataflow {
/// An interface for a SAT solver that can be used by dataflow analyses.
class Solver {
public:
enum class Result {
/// Indicates that there exists a satisfying assignment for a boolean
struct Result {
enum class Status {
/// Indicates that there exists a satisfying assignment for a boolean
/// formula.
Satisfiable,
/// Indicates that there is no satisfying assignment for a boolean
/// formula.
Unsatisfiable,
/// Indicates that the solver gave up trying to find a satisfying
/// assignment for a boolean formula.
TimedOut,
};
/// A boolean value is set to true or false in a truth assignment.
enum class Assignment : uint8_t { AssignedFalse = 0, AssignedTrue = 1 };
/// Constructs a result indicating that the queried boolean formula is
/// satisfiable. The result will hold a solution found by the solver.
static Result
Satisfiable(llvm::DenseMap<AtomicBoolValue *, Assignment> Solution) {
return Result(Status::Satisfiable, std::move(Solution));
}
/// Constructs a result indicating that the queried boolean formula is
/// unsatisfiable.
static Result Unsatisfiable() { return Result(Status::Unsatisfiable, {}); }
/// Constructs a result indicating that satisfiability checking on the
/// queried boolean formula was not completed.
static Result TimedOut() { return Result(Status::TimedOut, {}); }
/// Returns the status of satisfiability checking on the queried boolean
/// formula.
Satisfiable,
Status getStatus() const { return SATCheckStatus; }
/// Indicates that there is no satisfying assignment for a boolean formula.
Unsatisfiable,
/// Returns a truth assignment to boolean values that satisfies the queried
/// boolean formula if available. Otherwise, an empty optional is returned.
llvm::Optional<llvm::DenseMap<AtomicBoolValue *, Assignment>>
getSolution() const {
return Solution;
}
/// Indicates that the solver gave up trying to find a satisfying assignment
/// for a boolean formula.
TimedOut,
private:
Result(
enum Status SATCheckStatus,
llvm::Optional<llvm::DenseMap<AtomicBoolValue *, Assignment>> Solution)
: SATCheckStatus(SATCheckStatus), Solution(std::move(Solution)) {}
Status SATCheckStatus;
llvm::Optional<llvm::DenseMap<AtomicBoolValue *, Assignment>> Solution;
};
virtual ~Solver() = default;
@ -44,9 +87,6 @@ class Solver {
/// Requirements:
///
/// All elements in `Vals` must not be null.
///
/// FIXME: Consider returning a model in case the conjunction of `Vals` is
/// satisfiable so that it can be used to generate warning messages.
virtual Result solve(llvm::DenseSet<BoolValue *> Vals) = 0;
};

View File

@ -16,7 +16,7 @@ namespace clang {
template <typename... IdentifierInfos>
static inline Selector getKeywordSelector(ASTContext &Ctx,
IdentifierInfos *... IIs) {
static_assert(sizeof...(IdentifierInfos),
static_assert(sizeof...(IdentifierInfos) > 0,
"keyword selectors must have at least one argument");
SmallVector<IdentifierInfo *, 10> II({&Ctx.Idents.get(IIs)...});

View File

@ -26,8 +26,8 @@ inline llvm::VersionTuple alignedAllocMinVersion(llvm::Triple::OSType OS) {
default:
break;
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX: // Earliest supporting version is 10.14.
return llvm::VersionTuple(10U, 14U);
case llvm::Triple::MacOSX: // Earliest supporting version is 10.13.
return llvm::VersionTuple(10U, 13U);
case llvm::Triple::IOS:
case llvm::Triple::TvOS: // Earliest supporting version is 11.0.0.
return llvm::VersionTuple(11U);

View File

@ -4036,3 +4036,14 @@ def NoRandomizeLayout : InheritableAttr {
let LangOpts = [COnly];
}
def : MutualExclusions<[RandomizeLayout, NoRandomizeLayout]>;
def FunctionReturnThunks : InheritableAttr,
TargetSpecificAttr<TargetAnyX86> {
let Spellings = [GCC<"function_return">];
let Args = [EnumArgument<"ThunkType", "Kind",
["keep", "thunk-extern"],
["Keep", "Extern"]
>];
let Subjects = SubjectList<[Function]>;
let Documentation = [FunctionReturnThunksDocs];
}

View File

@ -3088,8 +3088,8 @@ def FormatDocs : Documentation {
let Content = [{
Clang supports the ``format`` attribute, which indicates that the function
accepts a ``printf`` or ``scanf``-like format string and corresponding
arguments or a ``va_list`` that contains these arguments.
accepts (among other possibilities) a ``printf`` or ``scanf``-like format string
and corresponding arguments or a ``va_list`` that contains these arguments.
Please see `GCC documentation about format attribute
<http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ to find details
@ -3143,6 +3143,27 @@ Clang implements two kinds of checks with this attribute.
In this case Clang does not warn because the format string ``s`` and
the corresponding arguments are annotated. If the arguments are
incorrect, the caller of ``foo`` will receive a warning.
As an extension to GCC's behavior, Clang accepts the ``format`` attribute on
non-variadic functions. Clang checks non-variadic format functions for the same
classes of issues that can be found on variadic functions, as controlled by the
same warning flags, except that the types of formatted arguments is forced by
the function signature. For example:
.. code-block:: c
__attribute__((__format__(__printf__, 1, 2)))
void fmt(const char *s, const char *a, int b);
void bar(void) {
fmt("%s %i", "hello", 123); // OK
fmt("%i %g", "hello", 123); // warning: arguments don't match format
extern const char *fmt;
fmt(fmt, "hello", 123); // warning: format string is not a string literal
}
Using the ``format`` attribute on a non-variadic function emits a GCC
compatibility diagnostic.
}];
}
@ -6585,6 +6606,28 @@ evaluate to NULL.
}
return 0;
}
}];
}
def FunctionReturnThunksDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
The attribute ``function_return`` can replace return instructions with jumps to
target-specific symbols. This attribute supports 2 possible values,
corresponding to the values supported by the ``-mfunction-return=`` command
line flag:
* ``__attribute__((function_return("keep")))`` to disable related transforms.
This is useful for undoing global setting from ``-mfunction-return=`` locally
for individual functions.
* ``__attribute__((function_return("thunk-extern")))`` to replace returns with
jumps, while NOT emitting the thunk.
The values ``thunk`` and ``thunk-inline`` from GCC are not supported.
The symbol used for ``thunk-extern`` is target specific:
* X86: ``__x86_return_thunk``
As such, this function attribute is currently only supported on X86 targets.
}];
}

View File

@ -825,6 +825,7 @@ BUILTIN(__rdtsc, "UOi", "")
BUILTIN(__builtin_ia32_rdtscp, "UOiUi*", "")
TARGET_BUILTIN(__builtin_ia32_rdpid, "Ui", "n", "rdpid")
TARGET_BUILTIN(__builtin_ia32_rdpru, "ULLii", "n", "rdpru")
// PKU
TARGET_BUILTIN(__builtin_ia32_rdpkru, "Ui", "n", "pku")

View File

@ -107,6 +107,7 @@ CODEGENOPT(CFProtectionReturn , 1, 0) ///< if -fcf-protection is
CODEGENOPT(CFProtectionBranch , 1, 0) ///< if -fcf-protection is
///< set to full or branch.
CODEGENOPT(IBTSeal, 1, 0) ///< set to optimize CFProtectionBranch.
CODEGENOPT(FunctionReturnThunks, 1, 0) ///< -mfunction-return={keep|thunk-extern}
CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is
///< enabled.

View File

@ -389,6 +389,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// On AArch64 this can only be "sp_el0".
std::string StackProtectorGuardReg;
/// Specify a symbol to be the guard value.
std::string StackProtectorGuardSymbol;
/// Path to ignorelist file specifying which objects
/// (files, functions) listed for instrumentation by sanitizer
/// coverage pass should actually not be instrumented.

View File

@ -60,8 +60,6 @@ def err_drv_no_cuda_libdevice : Error<
"cannot find libdevice for %0; provide path to different CUDA installation "
"via '--cuda-path', or pass '-nocudalib' to build without linking with "
"libdevice">;
def err_drv_no_rdc_new_driver : Error<
"Using '--offload-new-driver' requires '-fgpu-rdc'">;
def err_drv_no_rocm_device_lib : Error<
"cannot find ROCm device library%select{| for %1|for ABI version %1}0; provide its path via "

View File

@ -31,6 +31,7 @@ def GNUAnonymousStruct : DiagGroup<"gnu-anonymous-struct">;
def GNUAutoType : DiagGroup<"gnu-auto-type">;
def ArrayBounds : DiagGroup<"array-bounds">;
def ArrayBoundsPointerArithmetic : DiagGroup<"array-bounds-pointer-arithmetic">;
def ArrayParameter : DiagGroup<"array-parameter">;
def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">;
def Availability : DiagGroup<"availability">;
def Section : DiagGroup<"section">;
@ -187,6 +188,7 @@ def UnguardedAvailability : DiagGroup<"unguarded-availability",
def : DiagGroup<"partial-availability", [UnguardedAvailability]>;
def DeprecatedDynamicExceptionSpec
: DiagGroup<"deprecated-dynamic-exception-spec">;
def DeprecatedBuiltins : DiagGroup<"deprecated-builtins">;
def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">;
def DeprecatedRegister : DiagGroup<"deprecated-register">;
@ -209,6 +211,7 @@ def Deprecated : DiagGroup<"deprecated", [DeprecatedAnonEnumEnumConversion,
DeprecatedEnumCompareConditional,
DeprecatedEnumEnumConversion,
DeprecatedEnumFloatConversion,
DeprecatedBuiltins,
DeprecatedIncrementBool,
DeprecatedPragma,
DeprecatedRegister,
@ -978,6 +981,7 @@ def Extra : DiagGroup<"extra", [
]>;
def Most : DiagGroup<"most", [
ArrayParameter,
BoolOperation,
CharSubscript,
Comment,

View File

@ -113,6 +113,8 @@ def warn_four_char_character_literal : Warning<
// Unicode and UCNs
def err_invalid_utf8 : Error<
"source file is not valid UTF-8">;
def warn_invalid_utf8_in_comment : Extension<
"invalid UTF-8 in comment">, InGroup<DiagGroup<"invalid-utf8">>;
def err_character_not_allowed : Error<
"unexpected character <U+%0>">;
def err_character_not_allowed_identifier : Error<
@ -128,8 +130,15 @@ def warn_utf8_symbol_zero_width : Warning<
"some environments">, InGroup<DiagGroup<"unicode-zero-width">>;
def ext_delimited_escape_sequence : Extension<
"%select{delimited|named}0 escape sequences are a Clang extension">,
"%select{delimited|named}0 escape sequences are a "
"%select{Clang|C++2b}1 extension">,
InGroup<DiagGroup<"delimited-escape-sequence-extension">>;
def warn_cxx2b_delimited_escape_sequence : Warning<
"%select{delimited|named}0 escape sequences are "
"incompatible with C++ standards before C++2b">,
InGroup<CXXPre2bCompat>, DefaultIgnore;
def err_delimited_escape_empty : Error<
"delimited escape sequence cannot be empty">;
def err_delimited_escape_missing_brace: Error<

View File

@ -3115,8 +3115,6 @@ def note_ownership_returns_index_mismatch : Note<
"declared with index %0 here">;
def err_format_strftime_third_parameter : Error<
"strftime format attribute requires 3rd parameter to be 0">;
def err_format_attribute_requires_variadic : Error<
"format attribute requires variadic function">;
def err_format_attribute_not : Error<"format argument not a string type">;
def err_format_attribute_result_not : Error<"function does not return %0">;
def err_format_attribute_implicit_this_format_string : Error<
@ -3343,10 +3341,11 @@ def warn_assume_aligned_too_great
"alignment assumed">,
InGroup<DiagGroup<"builtin-assume-aligned-alignment">>;
def warn_not_xl_compatible
: Warning<"requesting an alignment of 16 bytes or greater for struct"
" members is not binary compatible with IBM XL C/C++ for AIX"
" 16.1.0 and older">,
: Warning<"alignment of 16 bytes for a struct member is not binary "
"compatible with IBM XL C/C++ for AIX 16.1.0 or older">,
InGroup<AIXCompat>;
def note_misaligned_member_used_here : Note<
"passing byval argument %0 with potentially incompatible alignment here">;
def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
"%q0 redeclared without %1 attribute: previous %1 ignored">,
InGroup<MicrosoftInconsistentDllImport>;
@ -4127,6 +4126,9 @@ def err_attribute_not_supported_on_arch
def warn_gcc_ignores_type_attr : Warning<
"GCC does not allow the %0 attribute to be written on a type">,
InGroup<GccCompat>;
def warn_gcc_requires_variadic_function : Warning<
"GCC requires a function with the %0 attribute to be variadic">,
InGroup<GccCompat>;
// Clang-Specific Attributes
def warn_attribute_iboutlet : Warning<
@ -4829,8 +4831,12 @@ def warn_cxx14_compat_template_nontype_parm_auto_type : Warning<
DefaultIgnore, InGroup<CXXPre17Compat>;
def err_template_param_default_arg_redefinition : Error<
"template parameter redefines default argument">;
def err_template_param_default_arg_inconsistent_redefinition : Error<
"template parameter default argument is inconsistent with previous definition">;
def note_template_param_prev_default_arg : Note<
"previous default template argument defined here">;
def note_template_param_prev_default_arg_in_other_module : Note<
"previous default template argument defined in module %0">;
def err_template_param_default_arg_missing : Error<
"template parameter missing a default argument">;
def ext_template_parameter_default_in_function_template : ExtWarn<
@ -5557,6 +5563,9 @@ def warn_deprecated_def : Warning<
def warn_unavailable_def : Warning<
"implementing unavailable method">,
InGroup<DeprecatedImplementations>, DefaultIgnore;
def warn_deprecated_builtin : Warning<
"builtin %0 is deprecated; use %1 instead">,
InGroup<DeprecatedBuiltins>;
def err_unavailable : Error<"%0 is unavailable">;
def err_property_method_unavailable :
Error<"property access is using %0 method which is unavailable">;
@ -6605,13 +6614,16 @@ def warn_addition_in_bitshift : Warning<
"'%1' will be evaluated first">, InGroup<ShiftOpParentheses>;
def warn_self_assignment_builtin : Warning<
"explicitly assigning value of variable of type %0 to itself">,
"explicitly assigning value of variable of type %0 to itself%select{|; did "
"you mean to assign to member %2?}1">,
InGroup<SelfAssignment>, DefaultIgnore;
def warn_self_assignment_overloaded : Warning<
"explicitly assigning value of variable of type %0 to itself">,
"explicitly assigning value of variable of type %0 to itself%select{|; did "
"you mean to assign to member %2?}1">,
InGroup<SelfAssignmentOverloaded>, DefaultIgnore;
def warn_self_move : Warning<
"explicitly moving variable of type %0 to itself">,
"explicitly moving variable of type %0 to itself%select{|; did you mean to "
"move to member %2?}1">,
InGroup<SelfMove>, DefaultIgnore;
def err_builtin_move_forward_unsupported : Error<
@ -9395,6 +9407,12 @@ def warn_array_index_exceeds_max_addressable_bounds : Warning<
def note_array_declared_here : Note<
"array %0 declared here">;
def warn_inconsistent_array_form : Warning<
"argument %0 of type %1 with mismatched bound">,
InGroup<ArrayParameter>, DefaultIgnore;
def note_previous_declaration_as : Note<
"previously declared as %0 here">;
def warn_printf_insufficient_data_args : Warning<
"more '%%' conversions than data arguments">, InGroup<FormatInsufficientArgs>;
def warn_printf_data_arg_not_used : Warning<

View File

@ -0,0 +1,23 @@
//===- MakeSupport.h - Make Utilities ---------------------------*- 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_BASIC_MAKESUPPORT_H
#define LLVM_CLANG_BASIC_MAKESUPPORT_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
namespace clang {
/// Quote target names for inclusion in GNU Make dependency files.
/// Only the characters '$', '#', ' ', '\t' are quoted.
void quoteMakeTarget(StringRef Target, SmallVectorImpl<char> &Res);
} // namespace clang
#endif // LLVM_CLANG_BASIC_MAKESUPPORT_H

View File

@ -222,9 +222,7 @@ class TargetInfo : public virtual TransferrableTargetInfo,
mutable VersionTuple PlatformMinVersion;
unsigned HasAlignMac68kSupport : 1;
unsigned RealTypeUsesObjCFPRetMask
: llvm::BitmaskEnumDetail::bitWidth(
(int)FloatModeKind::LLVM_BITMASK_LARGEST_ENUMERATOR);
unsigned RealTypeUsesObjCFPRetMask : llvm::BitWidth<FloatModeKind>;
unsigned ComplexLongDoubleUsesFP2Ret : 1;
unsigned HasBuiltinMSVaList : 1;
@ -893,7 +891,7 @@ class TargetInfo : public virtual TransferrableTargetInfo,
/// Check whether the given real type should use the "fpret" flavor of
/// Objective-C message passing on this target.
bool useObjCFPRetForRealType(FloatModeKind T) const {
return RealTypeUsesObjCFPRetMask & llvm::BitmaskEnumDetail::Underlying(T);
return (int)((FloatModeKind)RealTypeUsesObjCFPRetMask & T);
}
/// Check whether _Complex long double should use the "fp2ret" flavor

View File

@ -582,18 +582,8 @@ class IsFloat<string type> {
}
let HasUnMaskedOverloaded = false,
MaskedPolicy = NonePolicy,
ManualCodegen = [{
IntrinsicTypes = {ResultType, Ops[1]->getType()};
Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
}],
MaskedManualCodegen= [{
// Move mask to right before vl.
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
IntrinsicTypes = {ResultType, Ops[3]->getType()};
Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
}] in {
class RVVVLEMaskBuiltin : RVVBuiltin<"m", "mPCUe", "c"> {
MaskedPolicy = NonePolicy in {
class RVVVLEMaskBuiltin : RVVOutBuiltin<"m", "mPCUe", "c"> {
let Name = "vlm_v";
let IRName = "vlm";
let HasMasked = false;
@ -601,26 +591,15 @@ let HasUnMaskedOverloaded = false,
}
let HasUnMaskedOverloaded = false,
ManualCodegen = [{
IntrinsicTypes = {ResultType, Ops[1]->getType()};
Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
Ops.insert(Ops.begin(), llvm::UndefValue::get(ResultType));
}],
MaskedManualCodegen= [{
// Move mask to right before vl.
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
Ops.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
IntrinsicTypes = {ResultType, Ops[3]->getType()};
Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
}] in {
UnMaskedPolicy = HasPassthruOperand in {
multiclass RVVVLEBuiltin<list<string> types> {
let Name = NAME # "_v",
IRName = "vle",
MaskedIRName ="vle_mask" in {
foreach type = types in {
def : RVVBuiltin<"v", "vPCe", type>;
def : RVVOutBuiltin<"v", "vPCe", type>;
if !not(IsFloat<type>.val) then {
def : RVVBuiltin<"Uv", "UvPCUe", type>;
def : RVVOutBuiltin<"Uv", "UvPCUe", type>;
}
}
}
@ -685,61 +664,39 @@ multiclass RVVVLSEBuiltin<list<string> types> {
IRName = "vlse",
MaskedIRName ="vlse_mask",
HasUnMaskedOverloaded = false,
ManualCodegen = [{
IntrinsicTypes = {ResultType, Ops[2]->getType()};
Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
Ops.insert(Ops.begin(), llvm::UndefValue::get(ResultType));
}],
MaskedManualCodegen= [{
// Move mask to right before vl.
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
Ops.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
IntrinsicTypes = {ResultType, Ops[4]->getType()};
Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
}] in {
UnMaskedPolicy = HasPassthruOperand in {
foreach type = types in {
def : RVVBuiltin<"v", "vPCet", type>;
def : RVVOutBuiltin<"v", "vPCet", type>;
if !not(IsFloat<type>.val) then {
def : RVVBuiltin<"Uv", "UvPCUet", type>;
def : RVVOutBuiltin<"Uv", "UvPCUet", type>;
}
}
}
}
multiclass RVVIndexedLoad<string op> {
let ManualCodegen = [{
IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[2]->getType()};
Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
Ops.insert(Ops.begin(), llvm::UndefValue::get(ResultType));
}],
MaskedManualCodegen = [{
// Move mask to right before vl.
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
Ops.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
IntrinsicTypes = {ResultType, Ops[2]->getType(), Ops[4]->getType()};
Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
}] in {
foreach type = TypeList in {
foreach eew_list = EEWList[0-2] in {
defvar eew = eew_list[0];
defvar eew_type = eew_list[1];
let Name = op # eew # "_v", IRName = op, MaskedIRName = op # "_mask" in {
def: RVVBuiltin<"v", "vPCe" # eew_type # "Uv", type>;
if !not(IsFloat<type>.val) then {
def: RVVBuiltin<"Uv", "UvPCUe" # eew_type # "Uv", type>;
}
}
let UnMaskedPolicy = HasPassthruOperand in {
foreach type = TypeList in {
foreach eew_list = EEWList[0-2] in {
defvar eew = eew_list[0];
defvar eew_type = eew_list[1];
let Name = op # eew # "_v", IRName = op, MaskedIRName = op # "_mask" in {
def: RVVOutOp1Builtin<"v", "vPCe" # eew_type # "Uv", type>;
if !not(IsFloat<type>.val) then {
def: RVVOutOp1Builtin<"Uv", "UvPCUe" # eew_type # "Uv", type>;
}
}
defvar eew64 = "64";
defvar eew64_type = "(Log2EEW:6)";
let Name = op # eew64 # "_v", IRName = op, MaskedIRName = op # "_mask",
RequiredFeatures = ["RV64"] in {
def: RVVBuiltin<"v", "vPCe" # eew64_type # "Uv", type>;
if !not(IsFloat<type>.val) then {
def: RVVBuiltin<"Uv", "UvPCUe" # eew64_type # "Uv", type>;
}
}
}
defvar eew64 = "64";
defvar eew64_type = "(Log2EEW:6)";
let Name = op # eew64 # "_v", IRName = op, MaskedIRName = op # "_mask",
RequiredFeatures = ["RV64"] in {
def: RVVOutOp1Builtin<"v", "vPCe" # eew64_type # "Uv", type>;
if !not(IsFloat<type>.val) then {
def: RVVOutOp1Builtin<"Uv", "UvPCUe" # eew64_type # "Uv", type>;
}
}
}
}
}

View File

@ -1998,6 +1998,13 @@ def fcf_protection : Flag<["-"], "fcf-protection">, Group<f_Group>, Flags<[CoreO
HelpText<"Enable cf-protection in 'full' mode">;
def mibt_seal : Flag<["-"], "mibt-seal">, Group<m_Group>, Flags<[CoreOption, CC1Option]>,
HelpText<"Optimize fcf-protection=branch/full (requires LTO).">;
def mfunction_return_EQ : Joined<["-"], "mfunction-return=">,
Group<m_Group>, Flags<[CoreOption, CC1Option]>,
HelpText<"Replace returns with jumps to ``__x86_return_thunk`` (x86 only, error otherwise)">,
Values<"keep,thunk-extern">,
NormalizedValues<["Keep", "Extern"]>,
NormalizedValuesScope<"llvm::FunctionReturnThunksKind">,
MarshallingInfoEnum<CodeGenOpts<"FunctionReturnThunks">, "Keep">;
defm xray_instrument : BoolFOption<"xray-instrument",
LangOpts<"XRayInstrument">, DefaultFalse,
@ -3338,11 +3345,12 @@ def mhwmult_EQ : Joined<["-"], "mhwmult=">, Group<m_Group>;
def mglobal_merge : Flag<["-"], "mglobal-merge">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Enable merging of globals">;
def mhard_float : Flag<["-"], "mhard-float">, Group<m_Group>;
def miphoneos_version_min_EQ : Joined<["-"], "miphoneos-version-min=">, Group<m_Group>;
def mios_version_min_EQ : Joined<["-"], "mios-version-min=">,
Alias<miphoneos_version_min_EQ>, HelpText<"Set iOS deployment target">;
Group<m_Group>, HelpText<"Set iOS deployment target">;
def : Joined<["-"], "miphoneos-version-min=">,
Group<m_Group>, Alias<mios_version_min_EQ>;
def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min=">;
def miphonesimulator_version_min_EQ : Joined<["-"], "miphonesimulator-version-min=">, Alias<mios_simulator_version_min_EQ>;
def : Joined<["-"], "miphonesimulator-version-min=">, Alias<mios_simulator_version_min_EQ>;
def mkernel : Flag<["-"], "mkernel">, Group<m_Group>;
def mlinker_version_EQ : Joined<["-"], "mlinker-version=">,
Flags<[NoXarchOption]>;
@ -3354,10 +3362,10 @@ def mmlir : Separate<["-"], "mmlir">, Flags<[CoreOption,FC1Option,FlangOption]>,
def ffuchsia_api_level_EQ : Joined<["-"], "ffuchsia-api-level=">,
Group<m_Group>, Flags<[CC1Option]>, HelpText<"Set Fuchsia API level">,
MarshallingInfoInt<LangOpts<"FuchsiaAPILevel">>;
def mmacosx_version_min_EQ : Joined<["-"], "mmacosx-version-min=">,
Group<m_Group>, HelpText<"Set Mac OS X deployment target">;
def mmacos_version_min_EQ : Joined<["-"], "mmacos-version-min=">,
Group<m_Group>, Alias<mmacosx_version_min_EQ>;
Group<m_Group>, HelpText<"Set macOS deployment target">;
def : Joined<["-"], "mmacosx-version-min=">,
Group<m_Group>, Alias<mmacos_version_min_EQ>;
def mms_bitfields : Flag<["-"], "mms-bitfields">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard">,
MarshallingInfoFlag<LangOpts<"MSBitfields">>;
@ -3771,6 +3779,9 @@ def mstack_protector_guard_EQ : Joined<["-"], "mstack-protector-guard=">, Group<
def mstack_protector_guard_offset_EQ : Joined<["-"], "mstack-protector-guard-offset=">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Use the given offset for addressing the stack-protector guard">,
MarshallingInfoInt<CodeGenOpts<"StackProtectorGuardOffset">, "INT_MAX", "int">;
def mstack_protector_guard_symbol_EQ : Joined<["-"], "mstack-protector-guard-symbol=">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Use the given symbol for addressing the stack-protector guard">,
MarshallingInfoString<CodeGenOpts<"StackProtectorGuardSymbol">>;
def mstack_protector_guard_reg_EQ : Joined<["-"], "mstack-protector-guard-reg=">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Use the given reg for addressing the stack-protector guard">,
MarshallingInfoString<CodeGenOpts<"StackProtectorGuardReg">>;
@ -3939,7 +3950,7 @@ def module_file_info : Flag<["-"], "module-file-info">, Flags<[NoXarchOption,CC1
HelpText<"Provide information about a particular module file">;
def mthumb : Flag<["-"], "mthumb">, Group<m_Group>;
def mtune_EQ : Joined<["-"], "mtune=">, Group<m_Group>,
HelpText<"Only supported on X86 and RISC-V. Otherwise accepted for compatibility with GCC.">;
HelpText<"Only supported on X86, RISC-V and SystemZ. Otherwise accepted for compatibility with GCC.">;
def multi__module : Flag<["-"], "multi_module">;
def multiply__defined__unused : Separate<["-"], "multiply_defined_unused">;
def multiply__defined : Separate<["-"], "multiply_defined">;
@ -4570,6 +4581,8 @@ def mptwrite : Flag<["-"], "mptwrite">, Group<m_x86_Features_Group>;
def mno_ptwrite : Flag<["-"], "mno-ptwrite">, Group<m_x86_Features_Group>;
def mrdpid : Flag<["-"], "mrdpid">, Group<m_x86_Features_Group>;
def mno_rdpid : Flag<["-"], "mno-rdpid">, Group<m_x86_Features_Group>;
def mrdpru : Flag<["-"], "mrdpru">, Group<m_x86_Features_Group>;
def mno_rdpru : Flag<["-"], "mno-rdpru">, Group<m_x86_Features_Group>;
def mrdrnd : Flag<["-"], "mrdrnd">, Group<m_x86_Features_Group>;
def mno_rdrnd : Flag<["-"], "mno-rdrnd">, Group<m_x86_Features_Group>;
def mrtm : Flag<["-"], "mrtm">, Group<m_x86_Features_Group>;

View File

@ -190,6 +190,10 @@ class SyntaxOnlyAction : public ASTFrontendAction {
/// Dump information about the given module file, to be used for
/// basic debugging and discovery.
class DumpModuleInfoAction : public ASTFrontendAction {
public:
// Allow other tools (ex lldb) to direct output for their use.
llvm::raw_ostream *OutputStream = nullptr;
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override;

View File

@ -385,6 +385,7 @@ class Preprocessor {
bool atTopLevel() { return S <= 0; }
bool afterImportSeq() { return S == AfterImportSeq; }
bool afterTopLevelSeq() { return S == AfterTopLevelTokenSeq; }
private:
State S;
@ -397,6 +398,67 @@ class Preprocessor {
/// Our current position within a C++20 import-seq.
ImportSeq ImportSeqState = ImportSeq::AfterTopLevelTokenSeq;
/// Track whether we are in a Global Module Fragment
class TrackGMF {
public:
enum GMFState : int {
GMFActive = 1,
MaybeGMF = 0,
BeforeGMFIntroducer = -1,
GMFAbsentOrEnded = -2,
};
TrackGMF(GMFState S) : S(S) {}
/// Saw a semicolon.
void handleSemi() {
// If it is immediately after the first instance of the module keyword,
// then that introduces the GMF.
if (S == MaybeGMF)
S = GMFActive;
}
/// Saw an 'export' identifier.
void handleExport() {
// The presence of an 'export' keyword always ends or excludes a GMF.
S = GMFAbsentOrEnded;
}
/// Saw an 'import' identifier.
void handleImport(bool AfterTopLevelTokenSeq) {
// If we see this before any 'module' kw, then we have no GMF.
if (AfterTopLevelTokenSeq && S == BeforeGMFIntroducer)
S = GMFAbsentOrEnded;
}
/// Saw a 'module' identifier.
void handleModule(bool AfterTopLevelTokenSeq) {
// This was the first module identifier and not preceded by any token
// that would exclude a GMF. It could begin a GMF, but only if directly
// followed by a semicolon.
if (AfterTopLevelTokenSeq && S == BeforeGMFIntroducer)
S = MaybeGMF;
else
S = GMFAbsentOrEnded;
}
/// Saw any other token.
void handleMisc() {
// We saw something other than ; after the 'module' kw, so not a GMF.
if (S == MaybeGMF)
S = GMFAbsentOrEnded;
}
bool inGMF() { return S == GMFActive; }
private:
/// Track the transitions into and out of a Global Module Fragment,
/// if one is present.
GMFState S;
};
TrackGMF TrackGMFState = TrackGMF::BeforeGMFIntroducer;
/// Whether the module import expects an identifier next. Otherwise,
/// it expects a '.' or ';'.
bool ModuleImportExpectsIdentifier = false;
@ -2414,6 +2476,7 @@ class Preprocessor {
None,
ModuleBegin,
ModuleImport,
HeaderUnitImport,
SkippedModuleImport,
Failure,
} Kind;

View File

@ -0,0 +1,41 @@
//===--- HLSLExternalSemaSource.h - HLSL Sema Source ------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the HLSLExternalSemaSource interface.
//
//===----------------------------------------------------------------------===//
#ifndef CLANG_SEMA_HLSLEXTERNALSEMASOURCE_H
#define CLANG_SEMA_HLSLEXTERNALSEMASOURCE_H
#include "clang/Sema/ExternalSemaSource.h"
namespace clang {
class NamespaceDecl;
class Sema;
class HLSLExternalSemaSource : public ExternalSemaSource {
Sema *SemaPtr = nullptr;
NamespaceDecl *HLSLNamespace;
void defineHLSLVectorAlias();
public:
~HLSLExternalSemaSource() override;
/// Initialize the semantic source with the Sema instance
/// being used to perform semantic analysis on the abstract syntax
/// tree.
void InitializeSema(Sema &S) override;
/// Inform the semantic consumer that Sema is no longer available.
void ForgetSema() override { SemaPtr = nullptr; }
};
} // namespace clang
#endif // CLANG_SEMA_HLSLEXTERNALSEMASOURCE_H

View File

@ -2272,6 +2272,9 @@ class Sema final {
bool isAcceptableSlow(const NamedDecl *D, AcceptableKind Kind);
// Determine whether the module M belongs to the current TU.
bool isModuleUnitOfCurrentTU(const Module *M) const;
public:
/// Get the module unit whose scope we are currently within.
Module *getCurrentModule() const {
@ -5167,6 +5170,11 @@ class Sema final {
void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
SourceLocation OpLoc);
/// Returns a field in a CXXRecordDecl that has the same name as the decl \p
/// SelfAssigned when inside a CXXMethodDecl.
const FieldDecl *
getSelfAssignmentClassMemberCandidate(const ValueDecl *SelfAssigned);
/// Warn if we're implicitly casting from a _Nullable pointer type to a
/// _Nonnull one.
void diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType,
@ -12997,21 +13005,29 @@ class Sema final {
SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
unsigned ByteNo) const;
private:
void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
const ArraySubscriptExpr *ASE=nullptr,
bool AllowOnePastEnd=true, bool IndexNegated=false);
void CheckArrayAccess(const Expr *E);
enum FormatArgumentPassingKind {
FAPK_Fixed, // values to format are fixed (no C-style variadic arguments)
FAPK_Variadic, // values to format are passed as variadic arguments
FAPK_VAList, // values to format are passed in a va_list
};
// Used to grab the relevant information from a FormatAttr and a
// FunctionDeclaration.
struct FormatStringInfo {
unsigned FormatIdx;
unsigned FirstDataArg;
bool HasVAListArg;
FormatArgumentPassingKind ArgPassingKind;
};
static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
FormatStringInfo *FSI);
bool IsVariadic, FormatStringInfo *FSI);
private:
void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
const ArraySubscriptExpr *ASE = nullptr,
bool AllowOnePastEnd = true, bool IndexNegated = false);
void CheckArrayAccess(const Expr *E);
bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
const FunctionProtoType *Proto);
bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc,
@ -13023,6 +13039,8 @@ class Sema final {
ArrayRef<const Expr *> Args,
const FunctionProtoType *Proto, SourceLocation Loc);
void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg);
void CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl,
StringRef ParamName, QualType ArgTy, QualType ParamTy);
@ -13166,16 +13184,15 @@ class Sema final {
private:
bool CheckFormatArguments(const FormatAttr *Format,
ArrayRef<const Expr *> Args,
bool IsCXXMember,
VariadicCallType CallType,
SourceLocation Loc, SourceRange Range,
ArrayRef<const Expr *> Args, bool IsCXXMember,
VariadicCallType CallType, SourceLocation Loc,
SourceRange Range,
llvm::SmallBitVector &CheckedVarArgs);
bool CheckFormatArguments(ArrayRef<const Expr *> Args,
bool HasVAListArg, unsigned format_idx,
FormatArgumentPassingKind FAPK, unsigned format_idx,
unsigned firstDataArg, FormatStringType Type,
VariadicCallType CallType,
SourceLocation Loc, SourceRange range,
VariadicCallType CallType, SourceLocation Loc,
SourceRange range,
llvm::SmallBitVector &CheckedVarArgs);
void CheckAbsoluteValueFunction(const CallExpr *Call,

View File

@ -414,7 +414,8 @@ class CallEvent {
bool isArgumentConstructedDirectly(unsigned Index) const {
// This assumes that the object was not yet removed from the state.
return ExprEngine::getObjectUnderConstruction(
getState(), {getOriginExpr(), Index}, getLocationContext()).hasValue();
getState(), {getOriginExpr(), Index}, getLocationContext())
.has_value();
}
/// Some calls have parameter numbering mismatched from argument numbering.
@ -1018,7 +1019,7 @@ class CXXAllocatorCall : public AnyFunctionCall {
SVal getObjectUnderConstruction() const {
return ExprEngine::getObjectUnderConstruction(getState(), getOriginExpr(),
getLocationContext())
.getValue();
.value();
}
/// Number of non-placement arguments to the call. It is equal to 2 for

View File

@ -53,21 +53,17 @@ class ConditionTruthVal {
}
/// Return true if the constraint is perfectly constrained to 'true'.
bool isConstrainedTrue() const { return Val && Val.getValue(); }
bool isConstrainedTrue() const { return Val && Val.value(); }
/// Return true if the constraint is perfectly constrained to 'false'.
bool isConstrainedFalse() const { return Val && !Val.getValue(); }
bool isConstrainedFalse() const { return Val && !Val.value(); }
/// Return true if the constrained is perfectly constrained.
bool isConstrained() const {
return Val.hasValue();
}
bool isConstrained() const { return Val.has_value(); }
/// Return true if the constrained is underconstrained and we do not know
/// if the constraint is true of value.
bool isUnderconstrained() const {
return !Val.hasValue();
}
bool isUnderconstrained() const { return !Val.has_value(); }
};
class ConstraintManager {

View File

@ -344,7 +344,7 @@ class SMTConstraintManager : public clang::ento::SimpleConstraintManager {
if (!res)
Cached[hash] = ConditionTruthVal();
else
Cached[hash] = ConditionTruthVal(res.getValue());
Cached[hash] = ConditionTruthVal(res.value());
return Cached[hash];
}

View File

@ -209,8 +209,8 @@ class RVVType {
}
bool isValid() const { return Valid; }
bool isScalar() const { return Scale && Scale.getValue() == 0; }
bool isVector() const { return Scale && Scale.getValue() != 0; }
bool isScalar() const { return Scale && Scale.value() == 0; }
bool isVector() const { return Scale && Scale.value() != 0; }
bool isVector(unsigned Width) const {
return isVector() && ElementBitwidth == Width;
}
@ -225,6 +225,8 @@ class RVVType {
return isFloat() && ElementBitwidth == Width;
}
bool isPointer() const { return IsPointer; }
private:
// Verify RVV vector type and set Valid.
bool verifyType() const;

View File

@ -94,9 +94,9 @@ class CachedFileSystemEntry {
assert(!isDirectory() && "not a file");
assert(Contents && "contents not initialized");
if (auto *Directives = Contents->DepDirectives.load()) {
if (Directives->hasValue())
if (Directives->has_value())
return ArrayRef<dependency_directives_scan::Directive>(
Directives->getValue());
Directives->value());
}
return None;
}

View File

@ -47,12 +47,12 @@ struct FullDependencies {
/// Get the full command line.
///
/// \param LookupPCMPath This function is called to fill in "-fmodule-file="
/// arguments and the "-o" argument. It needs to return
/// a path for where the PCM for the given module is to
/// be located.
std::vector<std::string>
getCommandLine(std::function<StringRef(ModuleID)> LookupPCMPath) const;
/// \param LookupModuleOutput This function is called to fill in
/// "-fmodule-file=", "-o" and other output
/// arguments for dependencies.
std::vector<std::string> getCommandLine(
llvm::function_ref<std::string(const ModuleID &, ModuleOutputKind)>
LookupOutput) const;
/// Get the full command line, excluding -fmodule-file=" arguments.
std::vector<std::string> getCommandLineWithoutModulePaths() const;

View File

@ -65,6 +65,19 @@ struct ModuleIDHasher {
}
};
/// An output from a module compilation, such as the path of the module file.
enum class ModuleOutputKind {
/// The module file (.pcm). Required.
ModuleFile,
/// The path of the dependency file (.d), if any.
DependencyFile,
/// The null-separated list of names to use as the targets in the dependency
/// file, if any. Defaults to the value of \c ModuleFile, as in the driver.
DependencyTargets,
/// The path of the serialized diagnostic file (.dia), if any.
DiagnosticSerializationFile,
};
struct ModuleDeps {
/// The identifier of the module.
ModuleID ID;
@ -104,17 +117,25 @@ struct ModuleDeps {
// the primary TU.
bool ImportedByMainFile = false;
/// Whether the TU had a dependency file. The path in \c BuildInvocation is
/// cleared to avoid leaking the specific path from the TU into the module.
bool HadDependencyFile = false;
/// Whether the TU had serialized diagnostics. The path in \c BuildInvocation
/// is cleared to avoid leaking the specific path from the TU into the module.
bool HadSerializedDiagnostics = false;
/// Compiler invocation that can be used to build this module (without paths).
CompilerInvocation BuildInvocation;
/// Gets the canonical command line suitable for passing to clang.
///
/// \param LookupPCMPath This function is called to fill in "-fmodule-file="
/// arguments and the "-o" argument. It needs to return
/// a path for where the PCM for the given module is to
/// be located.
/// \param LookupModuleOutput This function is called to fill in
/// "-fmodule-file=", "-o" and other output
/// arguments.
std::vector<std::string> getCanonicalCommandLine(
std::function<StringRef(ModuleID)> LookupPCMPath) const;
llvm::function_ref<std::string(const ModuleID &, ModuleOutputKind)>
LookupModuleOutput) const;
/// Gets the canonical command line suitable for passing to clang, excluding
/// "-fmodule-file=" and "-o" arguments.

View File

@ -3166,7 +3166,7 @@ void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD,
/// declaration of a function with an exception specification is permitted
/// and preserved. Other type sugar (for instance, typedefs) is not.
QualType ASTContext::getFunctionTypeWithExceptionSpec(
QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI) {
QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI) const {
// Might have some parens.
if (const auto *PT = dyn_cast<ParenType>(Orig))
return getParenType(
@ -3194,7 +3194,7 @@ QualType ASTContext::getFunctionTypeWithExceptionSpec(
}
bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T,
QualType U) {
QualType U) const {
return hasSameType(T, U) ||
(getLangOpts().CPlusPlus17 &&
hasSameType(getFunctionTypeWithExceptionSpec(T, EST_None),
@ -4703,7 +4703,7 @@ QualType ASTContext::getUnresolvedUsingType(
QualType ASTContext::getAttributedType(attr::Kind attrKind,
QualType modifiedType,
QualType equivalentType) {
QualType equivalentType) const {
llvm::FoldingSetNodeID id;
AttributedType::Profile(id, attrKind, modifiedType, equivalentType);
@ -5707,6 +5707,9 @@ QualType ASTContext::getAutoTypeInternal(
!TypeConstraintConcept && !IsDependent)
return getAutoDeductType();
if (TypeConstraintConcept)
TypeConstraintConcept = TypeConstraintConcept->getCanonicalDecl();
// Look in the folding set for an existing type.
void *InsertPos = nullptr;
llvm::FoldingSetNodeID ID;
@ -6215,8 +6218,59 @@ bool ASTContext::hasSameTemplateName(const TemplateName &X,
getCanonicalTemplateName(Y).getAsVoidPointer();
}
bool ASTContext::isSameConstraintExpr(const Expr *XCE, const Expr *YCE) const {
if (!XCE != !YCE)
return false;
if (!XCE)
return true;
llvm::FoldingSetNodeID XCEID, YCEID;
XCE->Profile(XCEID, *this, /*Canonical=*/true);
YCE->Profile(YCEID, *this, /*Canonical=*/true);
return XCEID == YCEID;
}
bool ASTContext::isSameTypeConstraint(const TypeConstraint *XTC,
const TypeConstraint *YTC) const {
if (!XTC != !YTC)
return false;
if (!XTC)
return true;
auto *NCX = XTC->getNamedConcept();
auto *NCY = YTC->getNamedConcept();
if (!NCX || !NCY || !isSameEntity(NCX, NCY))
return false;
if (XTC->hasExplicitTemplateArgs() != YTC->hasExplicitTemplateArgs())
return false;
if (XTC->hasExplicitTemplateArgs())
if (XTC->getTemplateArgsAsWritten()->NumTemplateArgs !=
YTC->getTemplateArgsAsWritten()->NumTemplateArgs)
return false;
// Compare slowly by profiling.
//
// We couldn't compare the profiling result for the template
// args here. Consider the following example in different modules:
//
// template <__integer_like _Tp, C<_Tp> Sentinel>
// constexpr _Tp operator()(_Tp &&__t, Sentinel &&last) const {
// return __t;
// }
//
// When we compare the profiling result for `C<_Tp>` in different
// modules, it will compare the type of `_Tp` in different modules.
// However, the type of `_Tp` in different modules refer to different
// types here naturally. So we couldn't compare the profiling result
// for the template args directly.
return isSameConstraintExpr(XTC->getImmediatelyDeclaredConstraint(),
YTC->getImmediatelyDeclaredConstraint());
}
bool ASTContext::isSameTemplateParameter(const NamedDecl *X,
const NamedDecl *Y) {
const NamedDecl *Y) const {
if (X->getKind() != Y->getKind())
return false;
@ -6226,32 +6280,8 @@ bool ASTContext::isSameTemplateParameter(const NamedDecl *X,
return false;
if (TX->hasTypeConstraint() != TY->hasTypeConstraint())
return false;
const TypeConstraint *TXTC = TX->getTypeConstraint();
const TypeConstraint *TYTC = TY->getTypeConstraint();
if (!TXTC != !TYTC)
return false;
if (TXTC && TYTC) {
auto *NCX = TXTC->getNamedConcept();
auto *NCY = TYTC->getNamedConcept();
if (!NCX || !NCY || !isSameEntity(NCX, NCY))
return false;
if (TXTC->hasExplicitTemplateArgs() != TYTC->hasExplicitTemplateArgs())
return false;
if (TXTC->hasExplicitTemplateArgs()) {
auto *TXTCArgs = TXTC->getTemplateArgsAsWritten();
auto *TYTCArgs = TYTC->getTemplateArgsAsWritten();
if (TXTCArgs->NumTemplateArgs != TYTCArgs->NumTemplateArgs)
return false;
llvm::FoldingSetNodeID XID, YID;
for (auto &ArgLoc : TXTCArgs->arguments())
ArgLoc.getArgument().Profile(XID, X->getASTContext());
for (auto &ArgLoc : TYTCArgs->arguments())
ArgLoc.getArgument().Profile(YID, Y->getASTContext());
if (XID != YID)
return false;
}
}
return true;
return isSameTypeConstraint(TX->getTypeConstraint(),
TY->getTypeConstraint());
}
if (auto *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
@ -6267,8 +6297,8 @@ bool ASTContext::isSameTemplateParameter(const NamedDecl *X,
TY->getTemplateParameters());
}
bool ASTContext::isSameTemplateParameterList(const TemplateParameterList *X,
const TemplateParameterList *Y) {
bool ASTContext::isSameTemplateParameterList(
const TemplateParameterList *X, const TemplateParameterList *Y) const {
if (X->size() != Y->size())
return false;
@ -6276,19 +6306,46 @@ bool ASTContext::isSameTemplateParameterList(const TemplateParameterList *X,
if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I)))
return false;
const Expr *XRC = X->getRequiresClause();
const Expr *YRC = Y->getRequiresClause();
if (!XRC != !YRC)
return isSameConstraintExpr(X->getRequiresClause(), Y->getRequiresClause());
}
bool ASTContext::isSameDefaultTemplateArgument(const NamedDecl *X,
const NamedDecl *Y) const {
// If the type parameter isn't the same already, we don't need to check the
// default argument further.
if (!isSameTemplateParameter(X, Y))
return false;
if (XRC) {
llvm::FoldingSetNodeID XRCID, YRCID;
XRC->Profile(XRCID, *this, /*Canonical=*/true);
YRC->Profile(YRCID, *this, /*Canonical=*/true);
if (XRCID != YRCID)
if (auto *TTPX = dyn_cast<TemplateTypeParmDecl>(X)) {
auto *TTPY = cast<TemplateTypeParmDecl>(Y);
if (!TTPX->hasDefaultArgument() || !TTPY->hasDefaultArgument())
return false;
return hasSameType(TTPX->getDefaultArgument(), TTPY->getDefaultArgument());
}
return true;
if (auto *NTTPX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
auto *NTTPY = cast<NonTypeTemplateParmDecl>(Y);
if (!NTTPX->hasDefaultArgument() || !NTTPY->hasDefaultArgument())
return false;
Expr *DefaultArgumentX = NTTPX->getDefaultArgument()->IgnoreImpCasts();
Expr *DefaultArgumentY = NTTPY->getDefaultArgument()->IgnoreImpCasts();
llvm::FoldingSetNodeID XID, YID;
DefaultArgumentX->Profile(XID, *this, /*Canonical=*/true);
DefaultArgumentY->Profile(YID, *this, /*Canonical=*/true);
return XID == YID;
}
auto *TTPX = cast<TemplateTemplateParmDecl>(X);
auto *TTPY = cast<TemplateTemplateParmDecl>(Y);
if (!TTPX->hasDefaultArgument() || !TTPY->hasDefaultArgument())
return false;
const TemplateArgument &TAX = TTPX->getDefaultArgument().getArgument();
const TemplateArgument &TAY = TTPY->getDefaultArgument().getArgument();
return hasSameTemplateName(TAX.getAsTemplate(), TAY.getAsTemplate());
}
static NamespaceDecl *getNamespace(const NestedNameSpecifier *X) {
@ -6371,7 +6428,7 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A,
return true;
}
bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) {
bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const {
if (X == Y)
return true;
@ -6447,17 +6504,9 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) {
return false;
}
const Expr *XRC = FuncX->getTrailingRequiresClause();
const Expr *YRC = FuncY->getTrailingRequiresClause();
if (!XRC != !YRC)
if (!isSameConstraintExpr(FuncX->getTrailingRequiresClause(),
FuncY->getTrailingRequiresClause()))
return false;
if (XRC) {
llvm::FoldingSetNodeID XRCID, YRCID;
XRC->Profile(XRCID, *this, /*Canonical=*/true);
YRC->Profile(YRCID, *this, /*Canonical=*/true);
if (XRCID != YRCID)
return false;
}
auto GetTypeAsWritten = [](const FunctionDecl *FD) {
// Map to the first declaration that we've already merged into this one.
@ -6478,8 +6527,6 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) {
if (getLangOpts().CPlusPlus17 && XFPT && YFPT &&
(isUnresolvedExceptionSpec(XFPT->getExceptionSpecType()) ||
isUnresolvedExceptionSpec(YFPT->getExceptionSpecType())) &&
// FIXME: We could make isSameEntity const after we make
// hasSameFunctionTypeIgnoringExceptionSpec const.
hasSameFunctionTypeIgnoringExceptionSpec(XT, YT))
return true;
return false;
@ -6521,6 +6568,20 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) {
// and patterns match.
if (const auto *TemplateX = dyn_cast<TemplateDecl>(X)) {
const auto *TemplateY = cast<TemplateDecl>(Y);
// ConceptDecl wouldn't be the same if their constraint expression differs.
if (const auto *ConceptX = dyn_cast<ConceptDecl>(X)) {
const auto *ConceptY = cast<ConceptDecl>(Y);
const Expr *XCE = ConceptX->getConstraintExpr();
const Expr *YCE = ConceptY->getConstraintExpr();
assert(XCE && YCE && "ConceptDecl without constraint expression?");
llvm::FoldingSetNodeID XID, YID;
XCE->Profile(XID, *this, /*Canonical=*/true);
YCE->Profile(YID, *this, /*Canonical=*/true);
if (XID != YID)
return false;
}
return isSameEntity(TemplateX->getTemplatedDecl(),
TemplateY->getTemplatedDecl()) &&
isSameTemplateParameterList(TemplateX->getTemplateParameters(),

View File

@ -5667,11 +5667,6 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
D2->setPreviousDecl(Recent);
}
if (FromTemplated->isCompleteDefinition() &&
!ToTemplated->isCompleteDefinition()) {
// FIXME: Import definition!
}
return D2;
}
@ -5950,11 +5945,6 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
ToVarTD->setPreviousDecl(Recent);
}
if (DTemplated->isThisDeclarationADefinition() &&
!ToTemplated->isThisDeclarationADefinition()) {
// FIXME: Import definition!
}
return ToVarTD;
}

View File

@ -169,7 +169,7 @@ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl *VD) {
llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
if (ActiveAttr)
return ActiveAttr.getValue()->getMapType();
return ActiveAttr.value()->getMapType();
return llvm::None;
}
@ -177,7 +177,7 @@ llvm::Optional<OMPDeclareTargetDeclAttr::DevTypeTy>
OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl *VD) {
llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
if (ActiveAttr)
return ActiveAttr.getValue()->getDevType();
return ActiveAttr.value()->getDevType();
return llvm::None;
}
@ -185,7 +185,7 @@ llvm::Optional<SourceLocation>
OMPDeclareTargetDeclAttr::getLocation(const ValueDecl *VD) {
llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
if (ActiveAttr)
return ActiveAttr.getValue()->getRange().getBegin();
return ActiveAttr.value()->getRange().getBegin();
return llvm::None;
}

View File

@ -1007,6 +1007,12 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
}
}
if (auto *Def = D->getDefinition()) {
if (D->hasAttr<FinalAttr>()) {
Out << " final";
}
}
if (D->isCompleteDefinition()) {
// Print the base classes
if (D->getNumBases()) {

View File

@ -321,6 +321,12 @@ bool clang::analyze_format_string::ParseUTF8InvalidSpecifier(
clang::analyze_format_string::ArgType::MatchKind
ArgType::matchesType(ASTContext &C, QualType argTy) const {
// When using the format attribute in C++, you can receive a function or an
// array that will necessarily decay to a pointer when passed to the final
// format consumer. Apply decay before type comparison.
if (argTy->canDecayToPointerType())
argTy = C.getDecayedType(argTy);
if (Ptr) {
// It has to be a pointer.
const PointerType *PT = argTy->getAs<PointerType>();

View File

@ -496,7 +496,7 @@ ByteCodeExprGen<Emitter>::getGlobalIdx(const VarDecl *VD) {
template <class Emitter>
const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) {
if (auto *PT = dyn_cast<PointerType>(Ty))
if (const PointerType *PT = dyn_cast<PointerType>(Ty))
return PT->getPointeeType()->getAs<RecordType>();
else
return Ty->getAs<RecordType>();

View File

@ -699,7 +699,7 @@ static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
Stmt *BodyFarm::getBody(const FunctionDecl *D) {
Optional<Stmt *> &Val = Bodies[D];
if (Val)
return Val.getValue();
return Val.value();
Val = nullptr;
@ -874,7 +874,7 @@ Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
Optional<Stmt *> &Val = Bodies[D];
if (Val)
return Val.getValue();
return Val.value();
Val = nullptr;
// For now, we only synthesize getters.

View File

@ -36,7 +36,7 @@ buildStmtToBasicBlockMap(const CFG &Cfg) {
if (!Stmt)
continue;
StmtToBlock[Stmt.getValue().getStmt()] = Block;
StmtToBlock[Stmt.value().getStmt()] = Block;
}
if (const Stmt *TerminatorStmt = Block->getTerminatorStmt())
StmtToBlock[TerminatorStmt] = Block;

View File

@ -24,8 +24,8 @@ namespace dataflow {
StorageLocation &
DataflowAnalysisContext::getStableStorageLocation(QualType Type) {
assert(!Type.isNull());
if (Type->isStructureOrClassType() || Type->isUnionType()) {
if (!Type.isNull() &&
(Type->isStructureOrClassType() || Type->isUnionType())) {
// FIXME: Explore options to avoid eager initialization of fields as some of
// them might not be needed for a particular analysis.
llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs;
@ -57,8 +57,8 @@ DataflowAnalysisContext::getStableStorageLocation(const Expr &E) {
PointerValue &
DataflowAnalysisContext::getOrCreateNullPointerValue(QualType PointeeType) {
assert(!PointeeType.isNull());
auto CanonicalPointeeType = PointeeType.getCanonicalType();
auto CanonicalPointeeType =
PointeeType.isNull() ? PointeeType : PointeeType.getCanonicalType();
auto Res = NullPointerVals.try_emplace(CanonicalPointeeType, nullptr);
if (Res.second) {
auto &PointeeLoc = getStableStorageLocation(CanonicalPointeeType);

View File

@ -0,0 +1,197 @@
//===- DebugSupport.cpp -----------------------------------------*- 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 functions which generate more readable forms of data
// structures used in the dataflow analyses, for debugging purposes.
//
//===----------------------------------------------------------------------===//
#include <utility>
#include "clang/Analysis/FlowSensitive/DebugSupport.h"
#include "clang/Analysis/FlowSensitive/Solver.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/FormatCommon.h"
#include "llvm/Support/FormatVariadic.h"
namespace clang {
namespace dataflow {
using llvm::AlignStyle;
using llvm::fmt_pad;
using llvm::formatv;
namespace {
class DebugStringGenerator {
public:
explicit DebugStringGenerator(
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNamesArg)
: Counter(0), AtomNames(std::move(AtomNamesArg)) {
#ifndef NDEBUG
llvm::StringSet<> Names;
for (auto &N : AtomNames) {
assert(Names.insert(N.second).second &&
"The same name must not assigned to different atoms");
}
#endif
}
/// Returns a string representation of a boolean value `B`.
std::string debugString(const BoolValue &B, size_t Depth = 0) {
std::string S;
switch (B.getKind()) {
case Value::Kind::AtomicBool: {
S = getAtomName(&cast<AtomicBoolValue>(B));
break;
}
case Value::Kind::Conjunction: {
auto &C = cast<ConjunctionValue>(B);
auto L = debugString(C.getLeftSubValue(), Depth + 1);
auto R = debugString(C.getRightSubValue(), Depth + 1);
S = formatv("(and\n{0}\n{1})", L, R);
break;
}
case Value::Kind::Disjunction: {
auto &D = cast<DisjunctionValue>(B);
auto L = debugString(D.getLeftSubValue(), Depth + 1);
auto R = debugString(D.getRightSubValue(), Depth + 1);
S = formatv("(or\n{0}\n{1})", L, R);
break;
}
case Value::Kind::Negation: {
auto &N = cast<NegationValue>(B);
S = formatv("(not\n{0})", debugString(N.getSubVal(), Depth + 1));
break;
}
default:
llvm_unreachable("Unhandled value kind");
}
auto Indent = Depth * 4;
return formatv("{0}", fmt_pad(S, Indent, 0));
}
/// Returns a string representation of a set of boolean `Constraints` and the
/// `Result` of satisfiability checking on the `Constraints`.
std::string debugString(const std::vector<BoolValue *> &Constraints,
const Solver::Result &Result) {
auto Template = R"(
Constraints
------------
{0:$[
]}
------------
{1}.
{2}
)";
std::vector<std::string> ConstraintsStrings;
ConstraintsStrings.reserve(Constraints.size());
for (auto &Constraint : Constraints) {
ConstraintsStrings.push_back(debugString(*Constraint));
}
auto StatusString = debugString(Result.getStatus());
auto Solution = Result.getSolution();
auto SolutionString =
Solution.hasValue() ? "\n" + debugString(Solution.value()) : "";
return formatv(
Template,
llvm::make_range(ConstraintsStrings.begin(), ConstraintsStrings.end()),
StatusString, SolutionString);
}
private:
/// Returns a string representation of a truth assignment to atom booleans.
std::string debugString(
const llvm::DenseMap<AtomicBoolValue *, Solver::Result::Assignment>
&AtomAssignments) {
size_t MaxNameLength = 0;
for (auto &AtomName : AtomNames) {
MaxNameLength = std::max(MaxNameLength, AtomName.second.size());
}
std::vector<std::string> Lines;
for (auto &AtomAssignment : AtomAssignments) {
auto Line = formatv("{0} = {1}",
fmt_align(getAtomName(AtomAssignment.first),
AlignStyle::Left, MaxNameLength),
debugString(AtomAssignment.second));
Lines.push_back(Line);
}
llvm::sort(Lines.begin(), Lines.end());
return formatv("{0:$[\n]}", llvm::make_range(Lines.begin(), Lines.end()));
}
/// Returns a string representation of a boolean assignment to true or false.
std::string debugString(Solver::Result::Assignment Assignment) {
switch (Assignment) {
case Solver::Result::Assignment::AssignedFalse:
return "False";
case Solver::Result::Assignment::AssignedTrue:
return "True";
}
llvm_unreachable("Booleans can only be assigned true/false");
}
/// Returns a string representation of the result status of a SAT check.
std::string debugString(Solver::Result::Status Status) {
switch (Status) {
case Solver::Result::Status::Satisfiable:
return "Satisfiable";
case Solver::Result::Status::Unsatisfiable:
return "Unsatisfiable";
case Solver::Result::Status::TimedOut:
return "TimedOut";
}
llvm_unreachable("Unhandled SAT check result status");
}
/// Returns the name assigned to `Atom`, either user-specified or created by
/// default rules (B0, B1, ...).
std::string getAtomName(const AtomicBoolValue *Atom) {
auto Entry = AtomNames.try_emplace(Atom, formatv("B{0}", Counter));
if (Entry.second) {
Counter++;
}
return Entry.first->second;
}
// Keep track of number of atoms without a user-specified name, used to assign
// non-repeating default names to such atoms.
size_t Counter;
// Keep track of names assigned to atoms.
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames;
};
} // namespace
std::string
debugString(const BoolValue &B,
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames) {
return DebugStringGenerator(std::move(AtomNames)).debugString(B);
}
std::string
debugString(const std::vector<BoolValue *> &Constraints,
const Solver::Result &Result,
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames) {
return DebugStringGenerator(std::move(AtomNames))
.debugString(Constraints, Result);
}
} // namespace dataflow
} // namespace clang

View File

@ -51,7 +51,7 @@ class StmtToEnvMapImpl : public StmtToEnvMap {
assert(BlockIT != CFCtx.getStmtToBlock().end());
const auto &State = BlockToState[BlockIT->getSecond()->getBlockID()];
assert(State);
return &State.getValue().Env;
return &State.value().Env;
}
private:
@ -212,7 +212,7 @@ static TypeErasedDataflowAnalysisState computeBlockInputState(
if (!MaybePredState)
continue;
TypeErasedDataflowAnalysisState PredState = MaybePredState.getValue();
TypeErasedDataflowAnalysisState PredState = MaybePredState.value();
if (ApplyBuiltinTransfer) {
if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) {
const StmtToEnvMapImpl StmtToEnv(CFCtx, BlockStates);
@ -370,7 +370,7 @@ runTypeErasedDataflowAnalysis(
transferBlock(CFCtx, BlockStates, *Block, InitEnv, Analysis);
if (OldBlockState &&
Analysis.isEqualTypeErased(OldBlockState.getValue().Lattice,
Analysis.isEqualTypeErased(OldBlockState.value().Lattice,
NewBlockState.Lattice) &&
OldBlockState->Env.equivalentTo(NewBlockState.Env, Analysis)) {
// The state of `Block` didn't change after transfer so there's no need to

View File

@ -120,7 +120,13 @@ struct BooleanFormula {
/// clauses in the formula start from the element at index 1.
std::vector<ClauseID> NextWatched;
explicit BooleanFormula(Variable LargestVar) : LargestVar(LargestVar) {
/// Stores the variable identifier and value location for atomic booleans in
/// the formula.
llvm::DenseMap<Variable, AtomicBoolValue *> Atomics;
explicit BooleanFormula(Variable LargestVar,
llvm::DenseMap<Variable, AtomicBoolValue *> Atomics)
: LargestVar(LargestVar), Atomics(std::move(Atomics)) {
Clauses.push_back(0);
ClauseStarts.push_back(0);
NextWatched.push_back(0);
@ -180,28 +186,47 @@ BooleanFormula buildBooleanFormula(const llvm::DenseSet<BoolValue *> &Vals) {
// Map each sub-value in `Vals` to a unique variable.
llvm::DenseMap<BoolValue *, Variable> SubValsToVar;
// Store variable identifiers and value location of atomic booleans.
llvm::DenseMap<Variable, AtomicBoolValue *> Atomics;
Variable NextVar = 1;
{
std::queue<BoolValue *> UnprocessedSubVals;
for (BoolValue *Val : Vals)
UnprocessedSubVals.push(Val);
while (!UnprocessedSubVals.empty()) {
Variable Var = NextVar;
BoolValue *Val = UnprocessedSubVals.front();
UnprocessedSubVals.pop();
if (!SubValsToVar.try_emplace(Val, NextVar).second)
if (!SubValsToVar.try_emplace(Val, Var).second)
continue;
++NextVar;
// Visit the sub-values of `Val`.
if (auto *C = dyn_cast<ConjunctionValue>(Val)) {
switch (Val->getKind()) {
case Value::Kind::Conjunction: {
auto *C = cast<ConjunctionValue>(Val);
UnprocessedSubVals.push(&C->getLeftSubValue());
UnprocessedSubVals.push(&C->getRightSubValue());
} else if (auto *D = dyn_cast<DisjunctionValue>(Val)) {
break;
}
case Value::Kind::Disjunction: {
auto *D = cast<DisjunctionValue>(Val);
UnprocessedSubVals.push(&D->getLeftSubValue());
UnprocessedSubVals.push(&D->getRightSubValue());
} else if (auto *N = dyn_cast<NegationValue>(Val)) {
break;
}
case Value::Kind::Negation: {
auto *N = cast<NegationValue>(Val);
UnprocessedSubVals.push(&N->getSubVal());
break;
}
case Value::Kind::AtomicBool: {
Atomics[Var] = cast<AtomicBoolValue>(Val);
break;
}
default:
llvm_unreachable("buildBooleanFormula: unhandled value kind");
}
}
}
@ -212,7 +237,7 @@ BooleanFormula buildBooleanFormula(const llvm::DenseSet<BoolValue *> &Vals) {
return ValIt->second;
};
BooleanFormula Formula(NextVar - 1);
BooleanFormula Formula(NextVar - 1, std::move(Atomics));
std::vector<bool> ProcessedSubVals(NextVar, false);
// Add a conjunct for each variable that represents a top-level conjunction
@ -383,7 +408,7 @@ class WatchedLiteralsSolverImpl {
// If the root level is reached, then all possible assignments lead to
// a conflict.
if (Level == 0)
return WatchedLiteralsSolver::Result::Unsatisfiable;
return Solver::Result::Unsatisfiable();
// Otherwise, take the other branch at the most recent level where a
// decision was made.
@ -440,12 +465,29 @@ class WatchedLiteralsSolverImpl {
++I;
}
}
return WatchedLiteralsSolver::Result::Satisfiable;
return Solver::Result::Satisfiable(buildSolution());
}
private:
// Reverses forced moves until the most recent level where a decision was made
// on the assignment of a variable.
/// Returns a satisfying truth assignment to the atomic values in the boolean
/// formula.
llvm::DenseMap<AtomicBoolValue *, Solver::Result::Assignment>
buildSolution() {
llvm::DenseMap<AtomicBoolValue *, Solver::Result::Assignment> Solution;
for (auto &Atomic : Formula.Atomics) {
// A variable may have a definite true/false assignment, or it may be
// unassigned indicating its truth value does not affect the result of
// the formula. Unassigned variables are assigned to true as a default.
Solution[Atomic.second] =
VarAssignments[Atomic.first] == Assignment::AssignedFalse
? Solver::Result::Assignment::AssignedFalse
: Solver::Result::Assignment::AssignedTrue;
}
return Solution;
}
/// Reverses forced moves until the most recent level where a decision was
/// made on the assignment of a variable.
void reverseForcedMoves() {
for (; LevelStates[Level] == State::Forced; --Level) {
const Variable Var = LevelVars[Level];
@ -459,7 +501,7 @@ class WatchedLiteralsSolverImpl {
}
}
// Updates watched literals that are affected by a variable assignment.
/// Updates watched literals that are affected by a variable assignment.
void updateWatchedLiterals() {
const Variable Var = LevelVars[Level];
@ -592,7 +634,7 @@ class WatchedLiteralsSolverImpl {
};
Solver::Result WatchedLiteralsSolver::solve(llvm::DenseSet<BoolValue *> Vals) {
return Vals.empty() ? WatchedLiteralsSolver::Result::Satisfiable
return Vals.empty() ? Solver::Result::Satisfiable({{}})
: WatchedLiteralsSolverImpl(Vals).solve();
}

View File

@ -320,7 +320,7 @@ static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
Optional<bool> b = comparePiece(**X_I, **Y_I);
if (b)
return b.getValue();
return b.value();
}
return None;
@ -397,7 +397,7 @@ static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
}
Optional<bool> b = comparePath(X.path, Y.path);
assert(b);
return b.getValue();
return b.value();
}
void PathDiagnosticConsumer::FlushDiagnostics(

View File

@ -149,7 +149,7 @@ class CFGBlockValues {
const VarDecl *vd) {
const Optional<unsigned> &idx = declToIndex.getValueIndex(vd);
assert(idx);
return getValueVector(block)[idx.getValue()];
return getValueVector(block)[idx.value()];
}
};
@ -210,7 +210,7 @@ void CFGBlockValues::resetScratch() {
ValueVector::reference CFGBlockValues::operator[](const VarDecl *vd) {
const Optional<unsigned> &idx = declToIndex.getValueIndex(vd);
assert(idx);
return scratch[idx.getValue()];
return scratch[idx.value()];
}
//------------------------------------------------------------------------====//

View File

@ -61,8 +61,8 @@ LangStandard::Kind clang::getDefaultLanguageStandard(clang::Language Lang,
if (CLANG_DEFAULT_STD_C != LangStandard::lang_unspecified)
return CLANG_DEFAULT_STD_C;
// The PS4 and PS5 use C99 as the default C standard.
if (T.isPS())
// The PS4 uses C99 as the default C standard.
if (T.isPS4())
return LangStandard::lang_gnu99;
return LangStandard::lang_gnu17;
case Language::ObjC:

View File

@ -0,0 +1,35 @@
//===-- MakeSuport.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
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/MakeSupport.h"
void clang::quoteMakeTarget(StringRef Target, SmallVectorImpl<char> &Res) {
for (unsigned i = 0, e = Target.size(); i != e; ++i) {
switch (Target[i]) {
case ' ':
case '\t':
// Escape the preceding backslashes
for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j)
Res.push_back('\\');
// Escape the space/tab
Res.push_back('\\');
break;
case '$':
Res.push_back('$');
break;
case '#':
Res.push_back('\\');
break;
default:
break;
}
Res.push_back(Target[i]);
}
}

View File

@ -503,7 +503,7 @@ bool TargetInfo::initFeatureMap(
TargetInfo::CallingConvKind
TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
if (getCXXABI() != TargetCXXABI::Microsoft &&
(ClangABICompat4 || getTriple().getOS() == llvm::Triple::PS4))
(ClangABICompat4 || getTriple().isPS4()))
return CCK_ClangABI4OrPS4;
return CCK_Default;
}

View File

@ -252,7 +252,7 @@ bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
.Case("64bit", Is64Bit)
.Default(None);
if (Result)
return Result.getValue();
return Result.value();
if (ISAInfo->isSupportedExtensionFeature(Feature))
return ISAInfo->hasExtension(Feature);

View File

@ -123,6 +123,14 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
bool isValidTuneCPUName(StringRef Name) const override {
return isValidCPUName(Name);
}
void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override {
fillValidCPUList(Values);
}
bool setCPU(const std::string &Name) override {
CPU = Name;
ISARevision = getISARevision(CPU);

View File

@ -297,6 +297,8 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasCLDEMOTE = true;
} else if (Feature == "+rdpid") {
HasRDPID = true;
} else if (Feature == "+rdpru") {
HasRDPRU = true;
} else if (Feature == "+kl") {
HasKL = true;
} else if (Feature == "+widekl") {
@ -743,6 +745,8 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__WIDEKL__");
if (HasRDPID)
Builder.defineMacro("__RDPID__");
if (HasRDPRU)
Builder.defineMacro("__RDPRU__");
if (HasCLDEMOTE)
Builder.defineMacro("__CLDEMOTE__");
if (HasWAITPKG)
@ -926,6 +930,7 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
.Case("prfchw", true)
.Case("ptwrite", true)
.Case("rdpid", true)
.Case("rdpru", true)
.Case("rdrnd", true)
.Case("rdseed", true)
.Case("rtm", true)
@ -1021,6 +1026,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Case("prfchw", HasPRFCHW)
.Case("ptwrite", HasPTWRITE)
.Case("rdpid", HasRDPID)
.Case("rdpru", HasRDPRU)
.Case("rdrnd", HasRDRND)
.Case("rdseed", HasRDSEED)
.Case("retpoline-external-thunk", HasRetpolineExternalThunk)

View File

@ -125,6 +125,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
bool HasMOVBE = false;
bool HasPREFETCHWT1 = false;
bool HasRDPID = false;
bool HasRDPRU = false;
bool HasRetpolineExternalThunk = false;
bool HasLAHFSAHF = false;
bool HasWBNOINVD = false;
@ -424,8 +425,8 @@ class LLVM_LIBRARY_VISIBILITY X86_32TargetInfo : public X86TargetInfo {
// Use fpret for all types.
RealTypeUsesObjCFPRetMask =
(int)(FloatModeKind::Float | FloatModeKind::Double |
FloatModeKind::LongDouble);
(unsigned)(FloatModeKind::Float | FloatModeKind::Double |
FloatModeKind::LongDouble);
// x86-32 has atomics up to 8 bytes
MaxAtomicPromoteWidth = 64;
@ -704,7 +705,7 @@ class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
"64-i64:64-f80:128-n8:16:32:64-S128");
// Use fpret only for long double.
RealTypeUsesObjCFPRetMask = (int)FloatModeKind::LongDouble;
RealTypeUsesObjCFPRetMask = (unsigned)FloatModeKind::LongDouble;
// Use fp2ret for _Complex long double.
ComplexLongDoubleUsesFP2Ret = true;

View File

@ -788,6 +788,18 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
SI.registerCallbacks(PIC, &FAM);
PassBuilder PB(TM.get(), PTO, PGOOpt, &PIC);
// Enable verify-debuginfo-preserve-each for new PM.
DebugifyEachInstrumentation Debugify;
DebugInfoPerPass DebugInfoBeforePass;
if (CodeGenOpts.EnableDIPreservationVerify) {
Debugify.setDebugifyMode(DebugifyMode::OriginalDebugInfo);
Debugify.setDebugInfoBeforePass(DebugInfoBeforePass);
if (!CodeGenOpts.DIBugsReportFilePath.empty())
Debugify.setOrigDIVerifyBugsReportFilePath(
CodeGenOpts.DIBugsReportFilePath);
Debugify.registerCallbacks(PIC);
}
// Attempt to load pass plugins and register their callbacks with PB.
for (auto &PluginFN : CodeGenOpts.PassPlugins) {
auto PassPlugin = PassPlugin::Load(PluginFN);

View File

@ -212,8 +212,7 @@ static std::unique_ptr<MangleContext> InitDeviceMC(CodeGenModule &CGM) {
CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM)
: CGCUDARuntime(CGM), Context(CGM.getLLVMContext()),
TheModule(CGM.getModule()),
RelocatableDeviceCode(CGM.getLangOpts().GPURelocatableDeviceCode ||
CGM.getLangOpts().OffloadingNewDriver),
RelocatableDeviceCode(CGM.getLangOpts().GPURelocatableDeviceCode),
DeviceMC(InitDeviceMC(CGM)) {
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
@ -1116,7 +1115,8 @@ void CGNVCUDARuntime::createOffloadingEntries() {
llvm::OpenMPIRBuilder OMPBuilder(CGM.getModule());
OMPBuilder.initialize();
StringRef Section = "cuda_offloading_entries";
StringRef Section = CGM.getLangOpts().HIP ? "hip_offloading_entries"
: "cuda_offloading_entries";
for (KernelInfo &I : EmittedKernels)
OMPBuilder.emitOffloadingEntry(KernelHandles[I.Kernel],
getDeviceSideName(cast<NamedDecl>(I.D)), 0,
@ -1171,10 +1171,11 @@ llvm::Function *CGNVCUDARuntime::finalizeModule() {
}
return nullptr;
}
if (!(CGM.getLangOpts().OffloadingNewDriver && RelocatableDeviceCode))
if (CGM.getLangOpts().OffloadingNewDriver && RelocatableDeviceCode)
createOffloadingEntries();
else
return makeModuleCtorFunction();
createOffloadingEntries();
return nullptr;
}

View File

@ -1931,6 +1931,9 @@ void CodeGenModule::getDefaultFunctionAttributes(StringRef Name,
FuncAttrs.addAttribute(llvm::Attribute::Convergent);
}
// TODO: NoUnwind attribute should be added for other GPU modes OpenCL, HIP,
// SYCL, OpenMP offload. AFAIK, none of them support exceptions in device
// code.
if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) {
// Exceptions aren't supported in CUDA device code.
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);

View File

@ -1783,14 +1783,14 @@ namespace {
StartIndex = FieldIndex;
} else if (StartIndex) {
EHStack.pushCleanup<SanitizeDtorFieldRange>(
NormalAndEHCleanup, DD, StartIndex.getValue(), FieldIndex);
NormalAndEHCleanup, DD, StartIndex.value(), FieldIndex);
StartIndex = None;
}
}
void End() {
if (StartIndex)
EHStack.pushCleanup<SanitizeDtorFieldRange>(NormalAndEHCleanup, DD,
StartIndex.getValue(), -1);
StartIndex.value(), -1);
}
};
} // end anonymous namespace

View File

@ -6717,11 +6717,9 @@ llvm::Value *CGOpenMPRuntime::emitNumTeamsForTargetDirective(
default:
break;
}
} else if (DefaultNT == -1) {
return nullptr;
}
return Bld.getInt32(DefaultNT);
return llvm::ConstantInt::get(CGF.Int32Ty, DefaultNT);
}
static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
@ -10189,9 +10187,8 @@ llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc(
return UDMMap.lookup(D);
}
void CGOpenMPRuntime::emitTargetNumIterationsCall(
llvm::Value *CGOpenMPRuntime::emitTargetNumIterationsCall(
CodeGenFunction &CGF, const OMPExecutableDirective &D,
llvm::Value *DeviceID,
llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
const OMPLoopDirective &D)>
SizeEmitter) {
@ -10201,20 +10198,12 @@ void CGOpenMPRuntime::emitTargetNumIterationsCall(
if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
TD = getNestedDistributeDirective(CGM.getContext(), D);
if (!TD)
return;
return llvm::ConstantInt::get(CGF.Int64Ty, 0);
const auto *LD = cast<OMPLoopDirective>(TD);
auto &&CodeGen = [LD, DeviceID, SizeEmitter, &D, this](CodeGenFunction &CGF,
PrePostActionTy &) {
if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) {
llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc());
llvm::Value *Args[] = {RTLoc, DeviceID, NumIterations};
CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), OMPRTL___kmpc_push_target_tripcount_mapper),
Args);
}
};
emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
return NumIterations;
return llvm::ConstantInt::get(CGF.Int64Ty, 0);
}
void CGOpenMPRuntime::emitTargetCall(
@ -10308,26 +10297,34 @@ void CGOpenMPRuntime::emitTargetCall(
// Source location for the ident struct
llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc());
// Emit tripcount for the target loop-based directive.
emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter);
// Get tripcount for the target loop-based directive.
llvm::Value *NumIterations =
emitTargetNumIterationsCall(CGF, D, SizeEmitter);
// Arguments for the target kernel.
SmallVector<llvm::Value *> KernelArgs{
CGF.Builder.getInt32(/* Version */ 1),
PointerNum,
InputInfo.BasePointersArray.getPointer(),
InputInfo.PointersArray.getPointer(),
InputInfo.SizesArray.getPointer(),
MapTypesArray,
MapNamesArray,
InputInfo.MappersArray.getPointer(),
NumIterations};
// Arguments passed to the 'nowait' variant.
SmallVector<llvm::Value *> NoWaitKernelArgs{
CGF.Builder.getInt32(0),
llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
CGF.Builder.getInt32(0),
llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
};
bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
// The target region is an outlined function launched by the runtime
// via calls __tgt_target() or __tgt_target_teams().
//
// __tgt_target() launches a target region with one team and one thread,
// executing a serial region. This master thread may in turn launch
// more threads within its team upon encountering a parallel region,
// however, no additional teams can be launched on the device.
//
// __tgt_target_teams() launches a target region with one or more teams,
// each with one or more threads. This call is required for target
// constructs such as:
// 'target teams'
// 'target' / 'teams'
// 'target teams distribute parallel for'
// 'target parallel'
// and so on.
// via calls to __tgt_target_kernel().
//
// Note that on the host and CPU targets, the runtime implementation of
// these calls simply call the outlined function without forking threads.
@ -10338,70 +10335,15 @@ void CGOpenMPRuntime::emitTargetCall(
// In contrast, on the NVPTX target, the implementation of
// __tgt_target_teams() launches a GPU kernel with the requested number
// of teams and threads so no additional calls to the runtime are required.
if (NumTeams) {
// If we have NumTeams defined this means that we have an enclosed teams
// region. Therefore we also expect to have NumThreads defined. These two
// values should be defined in the presence of a teams directive,
// regardless of having any clauses associated. If the user is using teams
// but no clauses, these two values will be the default that should be
// passed to the runtime library - a 32-bit integer with the value zero.
assert(NumThreads && "Thread limit expression should be available along "
"with number of teams.");
SmallVector<llvm::Value *> OffloadingArgs = {
RTLoc,
DeviceID,
OutlinedFnID,
PointerNum,
InputInfo.BasePointersArray.getPointer(),
InputInfo.PointersArray.getPointer(),
InputInfo.SizesArray.getPointer(),
MapTypesArray,
MapNamesArray,
InputInfo.MappersArray.getPointer(),
NumTeams,
NumThreads};
if (HasNowait) {
// Add int32_t depNum = 0, void *depList = nullptr, int32_t
// noAliasDepNum = 0, void *noAliasDepList = nullptr.
OffloadingArgs.push_back(CGF.Builder.getInt32(0));
OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy));
OffloadingArgs.push_back(CGF.Builder.getInt32(0));
OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy));
}
Return = CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), HasNowait
? OMPRTL___tgt_target_teams_nowait_mapper
: OMPRTL___tgt_target_teams_mapper),
OffloadingArgs);
} else {
SmallVector<llvm::Value *> OffloadingArgs = {
RTLoc,
DeviceID,
OutlinedFnID,
PointerNum,
InputInfo.BasePointersArray.getPointer(),
InputInfo.PointersArray.getPointer(),
InputInfo.SizesArray.getPointer(),
MapTypesArray,
MapNamesArray,
InputInfo.MappersArray.getPointer()};
if (HasNowait) {
// Add int32_t depNum = 0, void *depList = nullptr, int32_t
// noAliasDepNum = 0, void *noAliasDepList = nullptr.
OffloadingArgs.push_back(CGF.Builder.getInt32(0));
OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy));
OffloadingArgs.push_back(CGF.Builder.getInt32(0));
OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy));
}
Return = CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), HasNowait ? OMPRTL___tgt_target_nowait_mapper
: OMPRTL___tgt_target_mapper),
OffloadingArgs);
}
// Check the error code and execute the host version if required.
CGF.Builder.restoreIP(
HasNoWait ? OMPBuilder.emitTargetKernel(
CGF.Builder, Return, RTLoc, DeviceID, NumTeams,
NumThreads, OutlinedFnID, KernelArgs, NoWaitKernelArgs)
: OMPBuilder.emitTargetKernel(CGF.Builder, Return, RTLoc,
DeviceID, NumTeams, NumThreads,
OutlinedFnID, KernelArgs));
llvm::BasicBlock *OffloadFailedBlock =
CGF.createBasicBlock("omp_offload.failed");
llvm::BasicBlock *OffloadContBlock =

View File

@ -884,13 +884,11 @@ class CGOpenMPRuntime {
llvm::Function *TaskFunction, QualType SharedsTy,
Address Shareds, const OMPTaskDataTy &Data);
/// Emit code that pushes the trip count of loops associated with constructs
/// 'target teams distribute' and 'teams distribute parallel for'.
/// \param SizeEmitter Emits the int64 value for the number of iterations of
/// the associated loop.
void emitTargetNumIterationsCall(
/// Return the trip count of loops associated with constructs / 'target teams
/// distribute' and 'teams distribute parallel for'. \param SizeEmitter Emits
/// the int64 value for the number of iterations of the associated loop.
llvm::Value *emitTargetNumIterationsCall(
CodeGenFunction &CGF, const OMPExecutableDirective &D,
llvm::Value *DeviceID,
llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
const OMPLoopDirective &D)>
SizeEmitter);

View File

@ -2591,11 +2591,12 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
}
}
static bool isSupportedByOpenMPIRBuilder(const OMPExecutableDirective &S) {
static bool isSupportedByOpenMPIRBuilder(const OMPSimdDirective &S) {
// Check for unsupported clauses
if (!S.clauses().empty()) {
// Currently no clause is supported
return false;
for (OMPClause *C : S.clauses()) {
// Currently only simdlen clause is supported
if (!isa<OMPSimdlenClause>(C))
return false;
}
// Check if we have a statement with the ordered directive.
@ -2630,7 +2631,6 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
// Use the OpenMPIRBuilder if enabled.
if (UseOMPIRBuilder) {
// Emit the associated statement and get its loop representation.
llvm::DebugLoc DL = SourceLocToDebugLoc(S.getBeginLoc());
const Stmt *Inner = S.getRawStmt();
llvm::CanonicalLoopInfo *CLI =
EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
@ -2638,7 +2638,15 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
// Add SIMD specific metadata
OMPBuilder.applySimd(DL, CLI);
llvm::ConstantInt *Simdlen = nullptr;
if (const auto *C = S.getSingleClause<OMPSimdlenClause>()) {
RValue Len =
this->EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(),
/*ignoreResult=*/true);
auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
Simdlen = Val;
}
OMPBuilder.applySimd(CLI, Simdlen);
return;
}
};
@ -5998,18 +6006,26 @@ static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
RMWOp = llvm::AtomicRMWInst::Xor;
break;
case BO_LT:
RMWOp = X.getType()->hasSignedIntegerRepresentation()
? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
: llvm::AtomicRMWInst::Max)
: (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
: llvm::AtomicRMWInst::UMax);
if (IsInteger)
RMWOp = X.getType()->hasSignedIntegerRepresentation()
? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
: llvm::AtomicRMWInst::Max)
: (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
: llvm::AtomicRMWInst::UMax);
else
RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMin
: llvm::AtomicRMWInst::FMax;
break;
case BO_GT:
RMWOp = X.getType()->hasSignedIntegerRepresentation()
? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
: llvm::AtomicRMWInst::Min)
: (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
: llvm::AtomicRMWInst::UMin);
if (IsInteger)
RMWOp = X.getType()->hasSignedIntegerRepresentation()
? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
: llvm::AtomicRMWInst::Min)
: (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
: llvm::AtomicRMWInst::UMin);
else
RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMax
: llvm::AtomicRMWInst::FMin;
break;
case BO_Assign:
RMWOp = llvm::AtomicRMWInst::Xchg;

View File

@ -898,6 +898,20 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
if (D && D->hasAttr<NoProfileFunctionAttr>())
Fn->addFnAttr(llvm::Attribute::NoProfile);
if (D) {
// Function attributes take precedence over command line flags.
if (auto *A = D->getAttr<FunctionReturnThunksAttr>()) {
switch (A->getThunkType()) {
case FunctionReturnThunksAttr::Kind::Keep:
break;
case FunctionReturnThunksAttr::Kind::Extern:
Fn->addFnAttr(llvm::Attribute::FnRetThunkExtern);
break;
}
} else if (CGM.getCodeGenOpts().FunctionReturnThunks)
Fn->addFnAttr(llvm::Attribute::FnRetThunkExtern);
}
if (FD && (getLangOpts().OpenCL ||
(getLangOpts().HIP && getLangOpts().CUDAIsDevice))) {
// Add metadata for a kernel function.

View File

@ -445,6 +445,7 @@ void CodeGenModule::checkAliases() {
void CodeGenModule::clear() {
DeferredDeclsToEmit.clear();
EmittedDeferredDecls.clear();
if (OpenMPRuntime)
OpenMPRuntime->clear();
}
@ -510,6 +511,9 @@ static void setVisibilityFromDLLStorageClass(const clang::LangOptions &LO,
void CodeGenModule::Release() {
EmitDeferred();
DeferredDecls.insert(EmittedDeferredDecls.begin(),
EmittedDeferredDecls.end());
EmittedDeferredDecls.clear();
EmitVTablesOpportunistically();
applyGlobalValReplacements();
applyReplacements();
@ -900,6 +904,9 @@ void CodeGenModule::Release() {
if (!getCodeGenOpts().StackProtectorGuardReg.empty())
getModule().setStackProtectorGuardReg(
getCodeGenOpts().StackProtectorGuardReg);
if (!getCodeGenOpts().StackProtectorGuardSymbol.empty())
getModule().setStackProtectorGuardSymbol(
getCodeGenOpts().StackProtectorGuardSymbol);
if (getCodeGenOpts().StackProtectorGuardOffset != INT_MAX)
getModule().setStackProtectorGuardOffset(
getCodeGenOpts().StackProtectorGuardOffset);
@ -4286,6 +4293,9 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
getCUDARuntime().handleVarRegistration(D, *GV);
}
if (D)
SanitizerMD->reportGlobal(GV, *D);
LangAS ExpectedAS =
D ? D->getType().getAddressSpace()
: (LangOpts.OpenCL ? LangAS::opencl_global : LangAS::Default);

View File

@ -344,6 +344,20 @@ class CodeGenModule : public CodeGenTypeCache {
std::vector<GlobalDecl> DeferredDeclsToEmit;
void addDeferredDeclToEmit(GlobalDecl GD) {
DeferredDeclsToEmit.emplace_back(GD);
addEmittedDeferredDecl(GD);
}
/// Decls that were DeferredDecls and have now been emitted.
llvm::DenseMap<llvm::StringRef, GlobalDecl> EmittedDeferredDecls;
void addEmittedDeferredDecl(GlobalDecl GD) {
if (!llvm::isa<FunctionDecl>(GD.getDecl()))
return;
llvm::GlobalVariable::LinkageTypes L = getFunctionLinkage(GD);
if (llvm::GlobalValue::isLinkOnceLinkage(L) ||
llvm::GlobalValue::isWeakLinkage(L)) {
EmittedDeferredDecls[getMangledName(GD)] = GD;
}
}
/// List of alias we have emitted. Used to make sure that what they point to
@ -1516,6 +1530,11 @@ class CodeGenModule : public CodeGenTypeCache {
NewBuilder->WeakRefReferences = std::move(WeakRefReferences);
NewBuilder->TBAA = std::move(TBAA);
assert(NewBuilder->EmittedDeferredDecls.empty() &&
"Still have (unmerged) EmittedDeferredDecls deferred decls");
NewBuilder->EmittedDeferredDecls = std::move(EmittedDeferredDecls);
}
private:

View File

@ -335,7 +335,42 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
if (auto *TTy = dyn_cast<RecordType>(Ty)) {
const RecordDecl *RD = TTy->getDecl()->getDefinition();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
SmallVector<llvm::MDBuilder::TBAAStructField, 4> Fields;
using TBAAStructField = llvm::MDBuilder::TBAAStructField;
SmallVector<TBAAStructField, 4> Fields;
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
// Handle C++ base classes. Non-virtual bases can treated a a kind of
// field. Virtual bases are more complex and omitted, but avoid an
// incomplete view for NewStructPathTBAA.
if (CodeGenOpts.NewStructPathTBAA && CXXRD->getNumVBases() != 0)
return BaseTypeMetadataCache[Ty] = nullptr;
for (const CXXBaseSpecifier &B : CXXRD->bases()) {
if (B.isVirtual())
continue;
QualType BaseQTy = B.getType();
const CXXRecordDecl *BaseRD = BaseQTy->getAsCXXRecordDecl();
if (BaseRD->isEmpty())
continue;
llvm::MDNode *TypeNode = isValidBaseType(BaseQTy)
? getBaseTypeInfo(BaseQTy)
: getTypeInfo(BaseQTy);
if (!TypeNode)
return BaseTypeMetadataCache[Ty] = nullptr;
uint64_t Offset = Layout.getBaseClassOffset(BaseRD).getQuantity();
uint64_t Size =
Context.getASTRecordLayout(BaseRD).getDataSize().getQuantity();
Fields.push_back(
llvm::MDBuilder::TBAAStructField(Offset, Size, TypeNode));
}
// The order in which base class subobjects are allocated is unspecified,
// so may differ from declaration order. In particular, Itanium ABI will
// allocate a primary base first.
// Since we exclude empty subobjects, the objects are not overlapping and
// their offsets are unique.
llvm::sort(Fields,
[](const TBAAStructField &A, const TBAAStructField &B) {
return A.Offset < B.Offset;
});
}
for (FieldDecl *Field : RD->fields()) {
if (Field->isZeroSize(Context) || Field->isUnnamedBitfield())
continue;

View File

@ -60,17 +60,17 @@ void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV,
Meta.NoHWAddress |= CGM.isInNoSanitizeList(
FsanitizeArgument.Mask & SanitizerKind::HWAddress, GV, Loc, Ty);
Meta.NoMemtag |= NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag);
Meta.NoMemtag |= CGM.isInNoSanitizeList(
Meta.Memtag |=
static_cast<bool>(FsanitizeArgument.Mask & SanitizerKind::MemtagGlobals);
Meta.Memtag &= !NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag);
Meta.Memtag &= !CGM.isInNoSanitizeList(
FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty);
if (FsanitizeArgument.has(SanitizerKind::Address)) {
// TODO(hctim): Make this conditional when we migrate off llvm.asan.globals.
IsDynInit &= !CGM.isInNoSanitizeList(SanitizerKind::Address |
SanitizerKind::KernelAddress,
GV, Loc, Ty, "init");
Meta.IsDynInit = IsDynInit;
}
Meta.IsDynInit = IsDynInit && !Meta.NoAddress &&
FsanitizeArgument.has(SanitizerKind::Address) &&
!CGM.isInNoSanitizeList(SanitizerKind::Address |
SanitizerKind::KernelAddress,
GV, Loc, Ty, "init");
GV->setSanitizerMetadata(Meta);
}

View File

@ -2930,7 +2930,7 @@ class OffloadingActionBuilder final {
return false;
Relocatable = Args.hasFlag(options::OPT_fgpu_rdc,
options::OPT_fno_gpu_rdc, /*Default=*/false);
options::OPT_fno_gpu_rdc, /*Default=*/false);
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
assert(HostTC && "No toolchain for host compilation.");
@ -3326,7 +3326,7 @@ class OffloadingActionBuilder final {
AssociatedOffloadKind);
if (CompileDeviceOnly && CurPhase == FinalPhase && BundleOutput &&
BundleOutput.getValue()) {
BundleOutput.value()) {
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
OffloadAction::DeviceDependences DDep;
DDep.add(*CudaDeviceActions[I], *ToolChains.front(), GpuArchList[I],
@ -4355,7 +4355,17 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
return KnownArchs.lookup(TC);
llvm::DenseSet<StringRef> Archs;
for (auto &Arg : Args) {
for (auto *Arg : Args) {
// Extract any '--[no-]offload-arch' arguments intended for this toolchain.
std::unique_ptr<llvm::opt::Arg> ExtractedArg = nullptr;
if (Arg->getOption().matches(options::OPT_Xopenmp_target_EQ) &&
ToolChain::getOpenMPTriple(Arg->getValue(0)) == TC->getTriple()) {
Arg->claim();
unsigned Index = Args.getBaseArgs().MakeIndex(Arg->getValue(1));
ExtractedArg = getOpts().ParseOneArg(Args, Index);
Arg = ExtractedArg.get();
}
if (Arg->getOption().matches(options::OPT_offload_arch_EQ)) {
for (StringRef Arch : llvm::split(Arg->getValue(), ","))
Archs.insert(getCanonicalArchString(C, Args, Arch, TC->getTriple()));
@ -4425,8 +4435,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
// Get the product of all bound architectures and toolchains.
SmallVector<std::pair<const ToolChain *, StringRef>> TCAndArchs;
for (const ToolChain *TC : ToolChains)
for (StringRef Arch : getOffloadArchs(
C, C.getArgsForToolChain(TC, "generic", Kind), Kind, TC))
for (StringRef Arch : getOffloadArchs(C, Args, Kind, TC))
TCAndArchs.push_back(std::make_pair(TC, Arch));
for (unsigned I = 0, E = TCAndArchs.size(); I != E; ++I)
@ -4477,11 +4486,23 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
if (offloadDeviceOnly())
return C.MakeAction<OffloadAction>(DDeps, types::TY_Nothing);
Action *OffloadPackager =
C.MakeAction<OffloadPackagerJobAction>(OffloadActions, types::TY_Image);
OffloadAction::DeviceDependences DDep;
DDep.add(*OffloadPackager, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
nullptr, Action::OFK_None);
if (C.isOffloadingHostKind(Action::OFK_Cuda) &&
!Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false)) {
// If we are not in RDC-mode we just emit the final CUDA fatbinary for each
// translation unit without requiring any linking.
Action *FatbinAction =
C.MakeAction<LinkJobAction>(OffloadActions, types::TY_CUDA_FATBIN);
DDep.add(*FatbinAction, *C.getSingleOffloadToolChain<Action::OFK_Cuda>(),
nullptr, Action::OFK_Cuda);
} else {
// Package all the offloading actions into a single output that can be
// embedded in the host and linked.
Action *PackagerAction =
C.MakeAction<OffloadPackagerJobAction>(OffloadActions, types::TY_Image);
DDep.add(*PackagerAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
nullptr, Action::OFK_None);
}
OffloadAction::HostDependence HDep(
*HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
/*BoundArch=*/nullptr, isa<CompileJobAction>(HostAction) ? DDep : DDeps);

View File

@ -437,7 +437,6 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
: getToolChain().GetProgramPath(getShortName());
ArgStringList CmdArgs;
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@ -476,8 +475,8 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
if (SectionAddressData) {
std::string DataSectionArg = std::string("-Tdata=0x") +
llvm::utohexstr(SectionAddressData.getValue());
std::string DataSectionArg =
std::string("-Tdata=0x") + llvm::utohexstr(SectionAddressData.value());
CmdArgs.push_back(Args.MakeArgString(DataSectionArg));
} else {
// We do not have an entry for this CPU in the address mapping table yet.
@ -503,6 +502,7 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Add the link library specific to the MCU.
CmdArgs.push_back(Args.MakeArgString(std::string("-l") + CPU));
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
CmdArgs.push_back("--end-group");
// Add user specified linker script.
@ -514,6 +514,8 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// than the bare minimum supports.
if (Linker.find("avr-ld") != std::string::npos)
CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName));
} else {
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
}
C.addCommand(std::make_unique<Command>(

View File

@ -27,6 +27,7 @@
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/MakeSupport.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
@ -51,6 +52,7 @@
#include "llvm/Support/Process.h"
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/YAMLParser.h"
#include <cctype>
using namespace clang::driver;
using namespace clang::driver::tools;
@ -97,34 +99,6 @@ static void EscapeSpacesAndBackslashes(const char *Arg,
}
}
// Quote target names for inclusion in GNU Make dependency files.
// Only the characters '$', '#', ' ', '\t' are quoted.
static void QuoteTarget(StringRef Target, SmallVectorImpl<char> &Res) {
for (unsigned i = 0, e = Target.size(); i != e; ++i) {
switch (Target[i]) {
case ' ':
case '\t':
// Escape the preceding backslashes
for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j)
Res.push_back('\\');
// Escape the space/tab
Res.push_back('\\');
break;
case '$':
Res.push_back('$');
break;
case '#':
Res.push_back('\\');
break;
default:
break;
}
Res.push_back(Target[i]);
}
}
/// Apply \a Work on the current tool chain \a RegularToolChain and any other
/// offloading tool chain that is associated with the current action \a JA.
static void
@ -567,7 +541,7 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args,
break;
}
if (Triple.isOSNetBSD()) {
if (Triple.isOSFuchsia() || Triple.isOSNetBSD()) {
return !areOptimizationsEnabled(Args);
}
@ -1144,7 +1118,7 @@ static void RenderDebugInfoCompressionArgs(const ArgList &Args,
if (Value == "none") {
CmdArgs.push_back("--compress-debug-sections=none");
} else if (Value == "zlib") {
if (llvm::zlib::isAvailable()) {
if (llvm::compression::zlib::isAvailable()) {
CmdArgs.push_back(
Args.MakeArgString("--compress-debug-sections=" + Twine(Value)));
} else {
@ -1249,7 +1223,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
} else {
CmdArgs.push_back("-MT");
SmallString<128> Quoted;
QuoteTarget(A->getValue(), Quoted);
quoteMakeTarget(A->getValue(), Quoted);
CmdArgs.push_back(Args.MakeArgString(Quoted));
}
}
@ -1274,7 +1248,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-MT");
SmallString<128> Quoted;
QuoteTarget(DepTarget, Quoted);
quoteMakeTarget(DepTarget, Quoted);
CmdArgs.push_back(Args.MakeArgString(Quoted));
}
@ -2228,8 +2202,23 @@ void Clang::AddSparcTargetArgs(const ArgList &Args,
void Clang::AddSystemZTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
bool HasBackchain = Args.hasFlag(options::OPT_mbackchain,
options::OPT_mno_backchain, false);
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) {
StringRef Name = A->getValue();
std::string TuneCPU;
if (Name == "native")
TuneCPU = std::string(llvm::sys::getHostCPUName());
else
TuneCPU = std::string(Name);
if (!TuneCPU.empty()) {
CmdArgs.push_back("-tune-cpu");
CmdArgs.push_back(Args.MakeArgString(TuneCPU));
}
}
bool HasBackchain =
Args.hasFlag(options::OPT_mbackchain, options::OPT_mno_backchain, false);
bool HasPackedStack = Args.hasFlag(options::OPT_mpacked_stack,
options::OPT_mno_packed_stack, false);
systemz::FloatABI FloatABI =
@ -2341,7 +2330,7 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,
if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(Args.MakeArgString("-hexagon-small-data-threshold=" +
Twine(G.getValue())));
Twine(G.value())));
}
if (!Args.hasArg(options::OPT_fno_short_enums))
@ -3231,6 +3220,16 @@ static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
}
static bool isValidSymbolName(StringRef S) {
if (S.empty())
return false;
if (std::isdigit(S[0]))
return false;
return llvm::all_of(S, [](char C) { return std::isalnum(C) || C == '_'; });
}
static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
const ArgList &Args, ArgStringList &CmdArgs,
bool KernelOrKext) {
@ -3362,6 +3361,16 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
}
A->render(Args, CmdArgs);
}
if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_symbol_EQ)) {
StringRef Value = A->getValue();
if (!isValidSymbolName(Value)) {
D.Diag(diag::err_drv_argument_only_allowed_with)
<< A->getOption().getName() << "legal symbol name";
return;
}
A->render(Args, CmdArgs);
}
}
static void RenderSCPOptions(const ToolChain &TC, const ArgList &Args,
@ -3750,38 +3759,49 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval);
Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after);
Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp);
if (HaveClangModules) {
Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp);
if (Arg *A = Args.getLastArg(options::OPT_fbuild_session_file)) {
if (Args.hasArg(options::OPT_fbuild_session_timestamp))
D.Diag(diag::err_drv_argument_not_allowed_with)
<< A->getAsString(Args) << "-fbuild-session-timestamp";
if (Arg *A = Args.getLastArg(options::OPT_fbuild_session_file)) {
if (Args.hasArg(options::OPT_fbuild_session_timestamp))
D.Diag(diag::err_drv_argument_not_allowed_with)
<< A->getAsString(Args) << "-fbuild-session-timestamp";
llvm::sys::fs::file_status Status;
if (llvm::sys::fs::status(A->getValue(), Status))
D.Diag(diag::err_drv_no_such_file) << A->getValue();
CmdArgs.push_back(Args.MakeArgString(
"-fbuild-session-timestamp=" +
Twine((uint64_t)std::chrono::duration_cast<std::chrono::seconds>(
Status.getLastModificationTime().time_since_epoch())
.count())));
}
llvm::sys::fs::file_status Status;
if (llvm::sys::fs::status(A->getValue(), Status))
D.Diag(diag::err_drv_no_such_file) << A->getValue();
CmdArgs.push_back(Args.MakeArgString(
"-fbuild-session-timestamp=" +
Twine((uint64_t)std::chrono::duration_cast<std::chrono::seconds>(
Status.getLastModificationTime().time_since_epoch())
.count())));
}
if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
if (!Args.getLastArg(options::OPT_fbuild_session_timestamp,
options::OPT_fbuild_session_file))
D.Diag(diag::err_drv_modules_validate_once_requires_timestamp);
if (Args.getLastArg(
options::OPT_fmodules_validate_once_per_build_session)) {
if (!Args.getLastArg(options::OPT_fbuild_session_timestamp,
options::OPT_fbuild_session_file))
D.Diag(diag::err_drv_modules_validate_once_requires_timestamp);
Args.AddLastArg(CmdArgs,
options::OPT_fmodules_validate_once_per_build_session);
}
if (Args.hasFlag(options::OPT_fmodules_validate_system_headers,
options::OPT_fno_modules_validate_system_headers,
ImplicitModules))
CmdArgs.push_back("-fmodules-validate-system-headers");
Args.AddLastArg(CmdArgs,
options::OPT_fmodules_validate_once_per_build_session);
options::OPT_fmodules_disable_diagnostic_validation);
} else {
Args.ClaimAllArgs(options::OPT_fbuild_session_timestamp);
Args.ClaimAllArgs(options::OPT_fbuild_session_file);
Args.ClaimAllArgs(options::OPT_fmodules_validate_once_per_build_session);
Args.ClaimAllArgs(options::OPT_fmodules_validate_system_headers);
Args.ClaimAllArgs(options::OPT_fno_modules_validate_system_headers);
Args.ClaimAllArgs(options::OPT_fmodules_disable_diagnostic_validation);
}
if (Args.hasFlag(options::OPT_fmodules_validate_system_headers,
options::OPT_fno_modules_validate_system_headers,
ImplicitModules))
CmdArgs.push_back("-fmodules-validate-system-headers");
Args.AddLastArg(CmdArgs, options::OPT_fmodules_disable_diagnostic_validation);
}
static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T,
@ -4422,12 +4442,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.hasFlag(options::OPT_offload_new_driver,
options::OPT_no_offload_new_driver, false));
bool IsRDCMode =
Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false);
bool IsUsingLTO = D.isUsingLTO(IsDeviceOffloadAction);
auto LTOMode = D.getLTOMode(IsDeviceOffloadAction);
// A header module compilation doesn't have a main input file, so invent a
// fake one as a placeholder.
const char *ModuleName = [&]{
const char *ModuleName = [&] {
auto *ModuleNameArg = Args.getLastArg(options::OPT_fmodule_name_EQ);
return ModuleNameArg ? ModuleNameArg->getValue() : "";
}();
@ -6285,10 +6307,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
if (IsCuda || IsHIP) {
if (!Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false) &&
Args.hasArg(options::OPT_offload_new_driver))
D.Diag(diag::err_drv_no_rdc_new_driver);
if (Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))
if (IsRDCMode)
CmdArgs.push_back("-fgpu-rdc");
if (Args.hasFlag(options::OPT_fgpu_defer_diag,
options::OPT_fno_gpu_defer_diag, false))
@ -6313,6 +6332,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (IsUsingLTO)
Args.AddLastArg(CmdArgs, options::OPT_mibt_seal);
if (Arg *A = Args.getLastArg(options::OPT_mfunction_return_EQ))
CmdArgs.push_back(
Args.MakeArgString(Twine("-mfunction-return=") + A->getValue()));
// Forward -f options with positive and negative forms; we translate these by
// hand. Do not propagate PGO options to the GPU-side compilations as the
// profile info is for the host-side compilation only.
@ -6956,13 +6979,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
// Host-side cuda compilation receives all device-side outputs in a single
// fatbin as Inputs[1]. Include the binary with -fcuda-include-gpubinary.
// Host-side offloading compilation receives all device-side outputs. Include
// them in the host compilation depending on the target. If the host inputs
// are not empty we use the new-driver scheme, otherwise use the old scheme.
if ((IsCuda || IsHIP) && CudaDeviceInput) {
CmdArgs.push_back("-fcuda-include-gpubinary");
CmdArgs.push_back(CudaDeviceInput->getFilename());
} else if (!HostOffloadingInputs.empty()) {
if (IsCuda && !IsRDCMode) {
assert(HostOffloadingInputs.size() == 1 && "Only one input expected");
CmdArgs.push_back("-fcuda-include-gpubinary");
CmdArgs.push_back(CudaDeviceInput->getFilename());
if (Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))
CmdArgs.push_back("-fgpu-rdc");
CmdArgs.push_back(HostOffloadingInputs.front().getFilename());
} else {
for (const InputInfo Input : HostOffloadingInputs)
CmdArgs.push_back(Args.MakeArgString("-fembed-offload-object=" +
TC.getInputFilename(Input)));
}
}
if (IsCuda) {
@ -7011,12 +7043,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
// Host-side offloading recieves the device object files and embeds it in a
// named section including the associated target triple and architecture.
for (const InputInfo Input : HostOffloadingInputs)
CmdArgs.push_back(Args.MakeArgString("-fembed-offload-object=" +
TC.getInputFilename(Input)));
if (Triple.isAMDGPU()) {
handleAMDGPUCodeObjectVersionOptions(D, Args, CmdArgs);
@ -8314,7 +8340,8 @@ void OffloadPackager::ConstructJob(Compilation &C, const JobAction &JA,
ArgStringList Features;
SmallVector<StringRef> FeatureArgs;
getTargetFeatures(TC->getDriver(), TC->getTriple(), Args, Features, false);
getTargetFeatures(TC->getDriver(), TC->getTriple(), TCArgs, Features,
false);
llvm::copy_if(Features, std::back_inserter(FeatureArgs),
[](StringRef Arg) { return !Arg.startswith("-target"); });
@ -8382,7 +8409,7 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
for (StringRef LibName : BCLibs)
CmdArgs.push_back(Args.MakeArgString(
"-target-library=" + Action::GetOffloadKindName(Action::OFK_OpenMP) +
"--bitcode-library=" + Action::GetOffloadKindName(Action::OFK_OpenMP) +
"-" + TC->getTripleString() + "-" + Arch + "=" + LibName));
}
@ -8402,63 +8429,64 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
} else if (A->getOption().matches(options::OPT_O0))
OOpt = "0";
if (!OOpt.empty())
CmdArgs.push_back(Args.MakeArgString(Twine("-opt-level=O") + OOpt));
CmdArgs.push_back(Args.MakeArgString(Twine("--opt-level=O") + OOpt));
}
}
CmdArgs.push_back("-host-triple");
CmdArgs.push_back(Args.MakeArgString(TheTriple.getTriple()));
CmdArgs.push_back(
Args.MakeArgString("--host-triple=" + TheTriple.getTriple()));
if (Args.hasArg(options::OPT_v))
CmdArgs.push_back("-v");
CmdArgs.push_back("--verbose");
// Add debug information if present.
if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
const Option &Opt = A->getOption();
if (Opt.matches(options::OPT_gN_Group)) {
if (Opt.matches(options::OPT_gline_directives_only) ||
Opt.matches(options::OPT_gline_tables_only))
CmdArgs.push_back("-gline-directives-only");
} else
CmdArgs.push_back("-g");
if (!A->getOption().matches(options::OPT_g0))
CmdArgs.push_back("--device-debug");
}
for (const auto &A : Args.getAllArgValues(options::OPT_Xcuda_ptxas))
CmdArgs.push_back(Args.MakeArgString("-ptxas-args=" + A));
CmdArgs.push_back(Args.MakeArgString("--ptxas-args=" + A));
// Forward remarks passes to the LLVM backend in the wrapper.
if (const Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
CmdArgs.push_back(
Args.MakeArgString(Twine("-pass-remarks=") + A->getValue()));
Args.MakeArgString(Twine("--pass-remarks=") + A->getValue()));
if (const Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ))
CmdArgs.push_back(
Args.MakeArgString(Twine("-pass-remarks-missed=") + A->getValue()));
Args.MakeArgString(Twine("--pass-remarks-missed=") + A->getValue()));
if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ))
CmdArgs.push_back(
Args.MakeArgString(Twine("-pass-remarks-analysis=") + A->getValue()));
Args.MakeArgString(Twine("--pass-remarks-analysis=") + A->getValue()));
if (Args.getLastArg(options::OPT_save_temps_EQ))
CmdArgs.push_back("-save-temps");
CmdArgs.push_back("--save-temps");
// Construct the link job so we can wrap around it.
Linker->ConstructJob(C, JA, Output, Inputs, Args, LinkingOutput);
const auto &LinkCommand = C.getJobs().getJobs().back();
// Forward -Xoffload-linker<-triple> arguments to the device link job.
for (auto *Arg : Args.filtered(options::OPT_Xoffload_linker)) {
StringRef Val = Arg->getValue(0);
for (Arg *A : Args.filtered(options::OPT_Xoffload_linker)) {
StringRef Val = A->getValue(0);
if (Val.empty())
CmdArgs.push_back(
Args.MakeArgString(Twine("-device-linker=") + Arg->getValue(1)));
Args.MakeArgString(Twine("--device-linker=") + A->getValue(1)));
else
CmdArgs.push_back(Args.MakeArgString(
"-device-linker=" +
"--device-linker=" +
ToolChain::getOpenMPTriple(Val.drop_front()).getTriple() + "=" +
Arg->getValue(1)));
A->getValue(1)));
}
Args.ClaimAllArgs(options::OPT_Xoffload_linker);
// Forward `-mllvm` arguments to the LLVM invocations if present.
for (Arg *A : Args.filtered(options::OPT_mllvm)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(A->getValue());
A->claim();
}
// Add the linker arguments to be forwarded by the wrapper.
CmdArgs.push_back("-linker-path");
CmdArgs.push_back(LinkCommand->getExecutable());
CmdArgs.push_back(Args.MakeArgString(Twine("--linker-path=") +
LinkCommand->getExecutable()));
CmdArgs.push_back("--");
for (const char *LinkArg : LinkCommand->getArguments())
CmdArgs.push_back(LinkArg);

View File

@ -727,7 +727,8 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
if (IsOffloadingHost)
CmdArgs.push_back("-lomptarget");
if (IsOffloadingHost && TC.getDriver().isUsingLTO(/* IsOffload */ true))
if (IsOffloadingHost && TC.getDriver().isUsingLTO(/* IsOffload */ true) &&
!Args.hasArg(options::OPT_nogpulib))
CmdArgs.push_back("-lomptarget.devicertl");
addArchSpecificRPath(TC, Args, CmdArgs);

View File

@ -1551,10 +1551,10 @@ struct DarwinPlatform {
options::ID Opt;
switch (Platform) {
case DarwinPlatformKind::MacOS:
Opt = options::OPT_mmacosx_version_min_EQ;
Opt = options::OPT_mmacos_version_min_EQ;
break;
case DarwinPlatformKind::IPhoneOS:
Opt = options::OPT_miphoneos_version_min_EQ;
Opt = options::OPT_mios_version_min_EQ;
break;
case DarwinPlatformKind::TvOS:
Opt = options::OPT_mtvos_version_min_EQ;
@ -1727,8 +1727,8 @@ struct DarwinPlatform {
Optional<DarwinPlatform>
getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
const Driver &TheDriver) {
Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ,
Arg *macOSVersion = Args.getLastArg(options::OPT_mmacos_version_min_EQ);
Arg *iOSVersion = Args.getLastArg(options::OPT_mios_version_min_EQ,
options::OPT_mios_simulator_version_min_EQ);
Arg *TvOSVersion =
Args.getLastArg(options::OPT_mtvos_version_min_EQ,
@ -1736,15 +1736,15 @@ getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
Arg *WatchOSVersion =
Args.getLastArg(options::OPT_mwatchos_version_min_EQ,
options::OPT_mwatchos_simulator_version_min_EQ);
if (OSXVersion) {
if (macOSVersion) {
if (iOSVersion || TvOSVersion || WatchOSVersion) {
TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
<< OSXVersion->getAsString(Args)
<< macOSVersion->getAsString(Args)
<< (iOSVersion ? iOSVersion
: TvOSVersion ? TvOSVersion : WatchOSVersion)
->getAsString(Args);
}
return DarwinPlatform::createOSVersionArg(Darwin::MacOS, OSXVersion);
return DarwinPlatform::createOSVersionArg(Darwin::MacOS, macOSVersion);
} else if (iOSVersion) {
if (TvOSVersion || WatchOSVersion) {
TheDriver.Diag(diag::err_drv_argument_not_allowed_with)

View File

@ -2087,7 +2087,7 @@ void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {
bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
if (BiarchSibling) {
M = BiarchSibling.getValue();
M = BiarchSibling.value();
return true;
}
return false;

View File

@ -340,8 +340,8 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-pie");
if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
CmdArgs.push_back(Args.MakeArgString("-G" + Twine(G.getValue())));
UseG0 = G.getValue() == 0;
CmdArgs.push_back(Args.MakeArgString("-G" + Twine(G.value())));
UseG0 = G.value() == 0;
}
CmdArgs.push_back("-o");

View File

@ -339,8 +339,9 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple.
static bool findGccVersion(StringRef LibDir, std::string &GccLibDir,
std::string &Ver) {
auto Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0");
std::string &Ver,
toolchains::Generic_GCC::GCCVersion &Version) {
Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0");
std::error_code EC;
for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE;
LI = LI.increment(EC)) {
@ -371,7 +372,7 @@ void toolchains::MinGW::findGccLibDir() {
for (StringRef CandidateSysroot : SubdirNames) {
llvm::SmallString<1024> LibDir(Base);
llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateSysroot);
if (findGccVersion(LibDir, GccLibDir, Ver)) {
if (findGccVersion(LibDir, GccLibDir, Ver, GccVer)) {
SubdirName = std::string(CandidateSysroot);
return;
}
@ -438,6 +439,11 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
getFilePaths().push_back(GccLibDir);
getFilePaths().push_back(
(Base + SubdirName + llvm::sys::path::get_separator() + "lib").str());
// Gentoo
getFilePaths().push_back(
(Base + SubdirName + llvm::sys::path::get_separator() + "mingw/lib").str());
getFilePaths().push_back(Base + "lib");
// openSUSE
getFilePaths().push_back(Base + SubdirName + "/sys-root/mingw/lib");
@ -593,6 +599,11 @@ void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addSystemInclude(DriverArgs, CC1Args,
Base + SubdirName + llvm::sys::path::get_separator() +
"include");
// Gentoo
addSystemInclude(DriverArgs, CC1Args,
Base + SubdirName + llvm::sys::path::get_separator() + "usr/include");
addSystemInclude(DriverArgs, CC1Args, Base + "include");
}
@ -620,7 +631,7 @@ void toolchains::MinGW::AddClangCXXStdlibIncludeArgs(
}
case ToolChain::CST_Libstdcxx:
llvm::SmallVector<llvm::SmallString<1024>, 4> CppIncludeBases;
llvm::SmallVector<llvm::SmallString<1024>, 7> CppIncludeBases;
CppIncludeBases.emplace_back(Base);
llvm::sys::path::append(CppIncludeBases[0], SubdirName, "include", "c++");
CppIncludeBases.emplace_back(Base);
@ -630,6 +641,15 @@ void toolchains::MinGW::AddClangCXXStdlibIncludeArgs(
llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver);
CppIncludeBases.emplace_back(GccLibDir);
llvm::sys::path::append(CppIncludeBases[3], "include", "c++");
CppIncludeBases.emplace_back(GccLibDir);
llvm::sys::path::append(CppIncludeBases[4], "include",
"g++-v" + GccVer.Text);
CppIncludeBases.emplace_back(GccLibDir);
llvm::sys::path::append(CppIncludeBases[5], "include",
"g++-v" + GccVer.MajorStr + "." + GccVer.MinorStr);
CppIncludeBases.emplace_back(GccLibDir);
llvm::sys::path::append(CppIncludeBases[6], "include",
"g++-v" + GccVer.MajorStr);
for (auto &CppIncludeBase : CppIncludeBases) {
addSystemInclude(DriverArgs, CC1Args, CppIncludeBase);
CppIncludeBase += Slash;

View File

@ -103,6 +103,7 @@ class LLVM_LIBRARY_VISIBILITY MinGW : public ToolChain {
std::string Base;
std::string GccLibDir;
clang::driver::toolchains::Generic_GCC::GCCVersion GccVer;
std::string Ver;
std::string SubdirName;
mutable std::unique_ptr<tools::gcc::Preprocessor> Preprocessor;

View File

@ -201,8 +201,11 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (D.CCCIsCXX()) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
CmdArgs.push_back("--start-group");
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lgloss");

View File

@ -31,14 +31,14 @@ namespace {
/// at position \p Key.
void serializeObject(Object &Paren, StringRef Key, Optional<Object> Obj) {
if (Obj)
Paren[Key] = std::move(Obj.getValue());
Paren[Key] = std::move(Obj.value());
}
/// Helper function to inject a JSON array \p Array into object \p Paren at
/// position \p Key.
void serializeArray(Object &Paren, StringRef Key, Optional<Array> Array) {
if (Array)
Paren[Key] = std::move(Array.getValue());
Paren[Key] = std::move(Array.value());
}
/// Serialize a \c VersionTuple \p V with the Symbol Graph semantic version

View File

@ -37,7 +37,7 @@ static bool shouldIndentWrappedSelectorName(const FormatStyle &Style,
// Returns the length of everything up to the first possible line break after
// the ), ], } or > matching \c Tok.
static unsigned getLengthToMatchingParen(const FormatToken &Tok,
const std::vector<ParenState> &Stack) {
const SmallVector<ParenState> &Stack) {
// Normally whether or not a break before T is possible is calculated and
// stored in T.CanBreakBefore. Braces, array initializers and text proto
// messages like `key: < ... >` are an exception: a break is possible
@ -404,6 +404,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
(State.Column + State.Line->Last->TotalLength - Previous.TotalLength >
getColumnLimit(State) ||
CurrentState.BreakBeforeParameter) &&
(!Current.isTrailingComment() || Current.NewlinesBefore > 0) &&
(Style.AllowShortFunctionsOnASingleLine != FormatStyle::SFS_All ||
Style.BreakConstructorInitializers != FormatStyle::BCIS_BeforeColon ||
Style.ColumnLimit != 0)) {
@ -793,6 +794,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
(Previous.is(tok::colon) && Previous.is(TT_ObjCMethodExpr)))) {
CurrentState.LastSpace = State.Column;
} else if (Previous.is(TT_CtorInitializerColon) &&
(!Current.isTrailingComment() || Current.NewlinesBefore > 0) &&
Style.BreakConstructorInitializers ==
FormatStyle::BCIS_AfterColon) {
CurrentState.Indent = State.Column;
@ -1032,7 +1034,7 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
// be considered bin packing unless the relevant AllowAll option is false or
// this is a dict/object literal.
bool PreviousIsBreakingCtorInitializerColon =
Previous.is(TT_CtorInitializerColon) &&
PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon;
if (!(Previous.isOneOf(tok::l_paren, tok::l_brace, TT_BinaryOperator) ||
PreviousIsBreakingCtorInitializerColon) ||

View File

@ -434,7 +434,7 @@ struct LineState {
/// A stack keeping track of properties applying to parenthesis
/// levels.
std::vector<ParenState> Stack;
SmallVector<ParenState> Stack;
/// Ignore the stack of \c ParenStates for state comparison.
///

View File

@ -2386,7 +2386,7 @@ class Cleaner : public TokenAnalyzer {
tooling::Replacements generateFixes() {
tooling::Replacements Fixes;
std::vector<FormatToken *> Tokens;
SmallVector<FormatToken *> Tokens;
std::copy(DeletedTokens.begin(), DeletedTokens.end(),
std::back_inserter(Tokens));
@ -2580,7 +2580,7 @@ struct JavaImportDirective {
StringRef Identifier;
StringRef Text;
unsigned Offset;
std::vector<StringRef> AssociatedCommentLines;
SmallVector<StringRef> AssociatedCommentLines;
bool IsStatic;
};
@ -2983,7 +2983,7 @@ tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code,
llvm::Regex ImportRegex(JavaImportRegexPattern);
SmallVector<StringRef, 4> Matches;
SmallVector<JavaImportDirective, 16> ImportsInBlock;
std::vector<StringRef> AssociatedCommentLines;
SmallVector<StringRef> AssociatedCommentLines;
bool FormattingOff = false;
@ -3433,17 +3433,19 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
}
const char *StyleOptionHelpDescription =
"Coding style, currently supports:\n"
" LLVM, GNU, Google, Chromium, Microsoft, Mozilla, WebKit.\n"
"Use -style=file to load style configuration from\n"
".clang-format file located in one of the parent\n"
"directories of the source file (or current\n"
"directory for stdin).\n"
"Use -style=file:<format_file_path> to explicitly specify\n"
"the configuration file.\n"
"Use -style=\"{key: value, ...}\" to set specific\n"
"parameters, e.g.:\n"
" -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
"Set coding style. <string> can be:\n"
"1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
" Mozilla, WebKit.\n"
"2. 'file' to load style configuration from a\n"
" .clang-format file in one of the parent directories\n"
" of the source file (for stdin, see --assume-filename).\n"
" If no .clang-format file is found, falls back to\n"
" --fallback-style.\n"
" --style=file is the default.\n"
"3. 'file:<format_file_path>' to explicitly specify\n"
" the configuration file.\n"
"4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
" --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
if (FileName.endswith(".java"))
@ -3498,6 +3500,7 @@ FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
return GuessedLanguage;
}
// Update StyleOptionHelpDescription above when changing this.
const char *DefaultFormatStyle = "file";
const char *DefaultFallbackStyle = "LLVM";

View File

@ -264,7 +264,7 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
// We can never place more than ColumnLimit / 3 items in a row (because of the
// spaces and the comma).
unsigned MaxItems = Style.ColumnLimit / 3;
std::vector<unsigned> MinSizeInColumn;
SmallVector<unsigned> MinSizeInColumn;
MinSizeInColumn.reserve(MaxItems);
for (unsigned Columns = 1; Columns <= MaxItems; ++Columns) {
ColumnFormat Format;

View File

@ -497,6 +497,15 @@ struct FormatToken {
// in a configured macro expansion.
llvm::Optional<MacroExpansion> MacroCtx;
/// When macro expansion introduces nodes with children, those are marked as
/// \c MacroParent.
/// FIXME: The formatting code currently hard-codes the assumption that
/// child nodes are introduced by blocks following an opening brace.
/// This is deeply baked into the code and disentangling this will require
/// signficant refactorings. \c MacroParent allows us to special-case the
/// cases in which we treat parents as block-openers for now.
bool MacroParent = false;
bool is(tok::TokenKind Kind) const { return Tok.is(Kind); }
bool is(TokenType TT) const { return getType() == TT; }
bool is(const IdentifierInfo *II) const {

View File

@ -0,0 +1,573 @@
//===--- MacroCallReconstructor.cpp - Format C++ code -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the implementation of MacroCallReconstructor, which fits
/// an reconstructed macro call to a parsed set of UnwrappedLines.
///
//===----------------------------------------------------------------------===//
#include "Macros.h"
#include "UnwrappedLineParser.h"
#include "clang/Basic/TokenKinds.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/Debug.h"
#include <cassert>
#define DEBUG_TYPE "format-reconstruct"
namespace clang {
namespace format {
// Call \p Call for each token in the unwrapped line given, passing
// the token, its parent and whether it is the first token in the line.
template <typename T>
void forEachToken(const UnwrappedLine &Line, const T &Call,
FormatToken *Parent = nullptr) {
bool First = true;
for (const auto &N : Line.Tokens) {
Call(N.Tok, Parent, First);
First = false;
for (const auto &Child : N.Children) {
forEachToken(Child, Call, N.Tok);
}
}
}
MacroCallReconstructor::MacroCallReconstructor(
unsigned Level,
const llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>>
&ActiveExpansions)
: Level(Level), IdToReconstructed(ActiveExpansions) {
Result.Tokens.push_back(std::make_unique<LineNode>());
ActiveReconstructedLines.push_back(&Result);
}
void MacroCallReconstructor::addLine(const UnwrappedLine &Line) {
assert(State != Finalized);
LLVM_DEBUG(llvm::dbgs() << "MCR: new line...\n");
forEachToken(Line, [&](FormatToken *Token, FormatToken *Parent, bool First) {
add(Token, Parent, First);
});
assert(InProgress || finished());
}
UnwrappedLine MacroCallReconstructor::takeResult() && {
finalize();
assert(Result.Tokens.size() == 1 && Result.Tokens.front()->Children.size() == 1);
UnwrappedLine Final =
createUnwrappedLine(*Result.Tokens.front()->Children.front(), Level);
assert(!Final.Tokens.empty());
return Final;
}
// Reconstruct the position of the next \p Token, given its parent \p
// ExpandedParent in the incoming unwrapped line. \p First specifies whether it
// is the first token in a given unwrapped line.
void MacroCallReconstructor::add(FormatToken *Token,
FormatToken *ExpandedParent, bool First) {
LLVM_DEBUG(
llvm::dbgs() << "MCR: Token: " << Token->TokenText << ", Parent: "
<< (ExpandedParent ? ExpandedParent->TokenText : "<null>")
<< ", First: " << First << "\n");
// In order to be able to find the correct parent in the reconstructed token
// stream, we need to continue the last open reconstruction until we find the
// given token if it is part of the reconstructed token stream.
//
// Note that hidden tokens can be part of the reconstructed stream in nested
// macro calls.
// For example, given
// #define C(x, y) x y
// #define B(x) {x}
// And the call:
// C(a, B(b))
// The outer macro call will be C(a, {b}), and the hidden token '}' can be
// found in the reconstructed token stream of that expansion level.
// In the expanded token stream
// a {b}
// 'b' is a child of '{'. We need to continue the open expansion of the ','
// in the call of 'C' in order to correctly set the ',' as the parent of '{',
// so we later set the spelled token 'b' as a child of the ','.
if (!ActiveExpansions.empty() && Token->MacroCtx &&
(Token->MacroCtx->Role != MR_Hidden ||
ActiveExpansions.size() != Token->MacroCtx->ExpandedFrom.size())) {
if (/*PassedMacroComma = */ reconstructActiveCallUntil(Token))
First = true;
}
prepareParent(ExpandedParent, First);
if (Token->MacroCtx) {
// If this token was generated by a macro call, add the reconstructed
// equivalent of the token.
reconstruct(Token);
} else {
// Otherwise, we add it to the current line.
appendToken(Token);
}
}
// Adjusts the stack of active reconstructed lines so we're ready to push
// tokens. The tokens to be pushed are children of ExpandedParent in the
// expanded code.
//
// This may entail:
// - creating a new line, if the parent is on the active line
// - popping active lines, if the parent is further up the stack
//
// Postcondition:
// ActiveReconstructedLines.back() is the line that has \p ExpandedParent or its
// reconstructed replacement token as a parent (when possible) - that is, the
// last token in \c ActiveReconstructedLines[ActiveReconstructedLines.size()-2]
// is the parent of ActiveReconstructedLines.back() in the reconstructed
// unwrapped line.
void MacroCallReconstructor::prepareParent(FormatToken *ExpandedParent,
bool NewLine) {
LLVM_DEBUG({
llvm::dbgs() << "ParentMap:\n";
debugParentMap();
});
// We want to find the parent in the new unwrapped line, where the expanded
// parent might have been replaced during reconstruction.
FormatToken *Parent = getParentInResult(ExpandedParent);
LLVM_DEBUG(llvm::dbgs() << "MCR: New parent: "
<< (Parent ? Parent->TokenText : "<null>") << "\n");
FormatToken *OpenMacroParent = nullptr;
if (!MacroCallStructure.empty()) {
// Inside a macro expansion, it is possible to lose track of the correct
// parent - either because it is already popped, for example because it was
// in a different macro argument (e.g. M({, })), or when we work on invalid
// code.
// Thus, we use the innermost macro call's parent as the parent at which
// we stop; this allows us to stay within the macro expansion and keeps
// any problems confined to the extent of the macro call.
OpenMacroParent =
getParentInResult(MacroCallStructure.back().MacroCallLParen);
LLVM_DEBUG(llvm::dbgs()
<< "MacroCallLParen: "
<< MacroCallStructure.back().MacroCallLParen->TokenText
<< ", OpenMacroParent: "
<< (OpenMacroParent ? OpenMacroParent->TokenText : "<null>")
<< "\n");
}
if (NewLine ||
(!ActiveReconstructedLines.back()->Tokens.empty() &&
Parent == ActiveReconstructedLines.back()->Tokens.back()->Tok)) {
// If we are at the first token in a new line, we want to also
// create a new line in the resulting reconstructed unwrapped line.
while (ActiveReconstructedLines.back()->Tokens.empty() ||
(Parent != ActiveReconstructedLines.back()->Tokens.back()->Tok &&
ActiveReconstructedLines.back()->Tokens.back()->Tok !=
OpenMacroParent)) {
ActiveReconstructedLines.pop_back();
assert(!ActiveReconstructedLines.empty());
}
assert(!ActiveReconstructedLines.empty());
ActiveReconstructedLines.back()->Tokens.back()->Children.push_back(
std::make_unique<ReconstructedLine>());
ActiveReconstructedLines.push_back(
&*ActiveReconstructedLines.back()->Tokens.back()->Children.back());
} else if (parentLine().Tokens.back()->Tok != Parent) {
// If we're not the first token in a new line, pop lines until we find
// the child of \c Parent in the stack.
while (Parent != parentLine().Tokens.back()->Tok &&
parentLine().Tokens.back()->Tok &&
parentLine().Tokens.back()->Tok != OpenMacroParent) {
ActiveReconstructedLines.pop_back();
assert(!ActiveReconstructedLines.empty());
}
}
assert(!ActiveReconstructedLines.empty());
}
// For a given \p Parent in the incoming expanded token stream, find the
// corresponding parent in the output.
FormatToken *MacroCallReconstructor::getParentInResult(FormatToken *Parent) {
FormatToken *Mapped = SpelledParentToReconstructedParent.lookup(Parent);
if (!Mapped)
return Parent;
for (; Mapped; Mapped = SpelledParentToReconstructedParent.lookup(Parent)) {
Parent = Mapped;
}
// If we use a different token than the parent in the expanded token stream
// as parent, mark it as a special parent, so the formatting code knows it
// needs to have its children formatted.
Parent->MacroParent = true;
return Parent;
}
// Reconstruct a \p Token that was expanded from a macro call.
void MacroCallReconstructor::reconstruct(FormatToken *Token) {
assert(Token->MacroCtx);
// A single token can be the only result of a macro call:
// Given: #define ID(x, y) ;
// And the call: ID(<some>, <tokens>)
// ';' in the expanded stream will reconstruct all of ID(<some>, <tokens>).
if (Token->MacroCtx->StartOfExpansion) {
startReconstruction(Token);
// If the order of tokens in the expanded token stream is not the
// same as the order of tokens in the reconstructed stream, we need
// to reconstruct tokens that arrive later in the stream.
if (Token->MacroCtx->Role != MR_Hidden) {
reconstructActiveCallUntil(Token);
}
}
assert(!ActiveExpansions.empty());
if (ActiveExpansions.back().SpelledI != ActiveExpansions.back().SpelledE) {
assert(ActiveExpansions.size() == Token->MacroCtx->ExpandedFrom.size());
if (Token->MacroCtx->Role != MR_Hidden) {
// The current token in the reconstructed token stream must be the token
// we're looking for - we either arrive here after startReconstruction,
// which initiates the stream to the first token, or after
// continueReconstructionUntil skipped until the expected token in the
// reconstructed stream at the start of add(...).
assert(ActiveExpansions.back().SpelledI->Tok == Token);
processNextReconstructed();
} else if (!currentLine()->Tokens.empty()) {
// Map all hidden tokens to the last visible token in the output.
// If the hidden token is a parent, we'll use the last visible
// token as the parent of the hidden token's children.
SpelledParentToReconstructedParent[Token] =
currentLine()->Tokens.back()->Tok;
} else {
for (auto I = ActiveReconstructedLines.rbegin(),
E = ActiveReconstructedLines.rend();
I != E; ++I) {
if (!(*I)->Tokens.empty()) {
SpelledParentToReconstructedParent[Token] = (*I)->Tokens.back()->Tok;
break;
}
}
}
}
if (Token->MacroCtx->EndOfExpansion)
endReconstruction(Token);
}
// Given a \p Token that starts an expansion, reconstruct the beginning of the
// macro call.
// For example, given: #define ID(x) x
// And the call: ID(int a)
// Reconstructs: ID(
void MacroCallReconstructor::startReconstruction(FormatToken *Token) {
assert(Token->MacroCtx);
assert(!Token->MacroCtx->ExpandedFrom.empty());
assert(ActiveExpansions.size() <= Token->MacroCtx->ExpandedFrom.size());
#ifndef NDEBUG
// Check that the token's reconstruction stack matches our current
// reconstruction stack.
for (size_t I = 0; I < ActiveExpansions.size(); ++I) {
assert(ActiveExpansions[I].ID ==
Token->MacroCtx
->ExpandedFrom[Token->MacroCtx->ExpandedFrom.size() - 1 - I]);
}
#endif
// Start reconstruction for all calls for which this token is the first token
// generated by the call.
// Note that the token's expanded from stack is inside-to-outside, and the
// expansions for which this token is not the first are the outermost ones.
ArrayRef<FormatToken *> StartedMacros =
makeArrayRef(Token->MacroCtx->ExpandedFrom)
.drop_back(ActiveExpansions.size());
assert(StartedMacros.size() == Token->MacroCtx->StartOfExpansion);
// We reconstruct macro calls outside-to-inside.
for (FormatToken *ID : llvm::reverse(StartedMacros)) {
// We found a macro call to be reconstructed; the next time our
// reconstruction stack is empty we know we finished an reconstruction.
#ifndef NDEBUG
State = InProgress;
#endif
// Put the reconstructed macro call's token into our reconstruction stack.
auto IU = IdToReconstructed.find(ID);
assert(IU != IdToReconstructed.end());
ActiveExpansions.push_back(
{ID, IU->second->Tokens.begin(), IU->second->Tokens.end()});
// Process the macro call's identifier.
processNextReconstructed();
if (ActiveExpansions.back().SpelledI == ActiveExpansions.back().SpelledE)
continue;
if (ActiveExpansions.back().SpelledI->Tok->is(tok::l_paren)) {
// Process the optional opening parenthesis.
processNextReconstructed();
}
}
}
// Add all tokens in the reconstruction stream to the output until we find the
// given \p Token.
bool MacroCallReconstructor::reconstructActiveCallUntil(FormatToken *Token) {
assert(!ActiveExpansions.empty());
bool PassedMacroComma = false;
// FIXME: If Token was already expanded earlier, due to
// a change in order, we will not find it, but need to
// skip it.
while (ActiveExpansions.back().SpelledI != ActiveExpansions.back().SpelledE &&
ActiveExpansions.back().SpelledI->Tok != Token) {
PassedMacroComma = processNextReconstructed() || PassedMacroComma;
}
return PassedMacroComma;
}
// End all reconstructions for which \p Token is the final token.
void MacroCallReconstructor::endReconstruction(FormatToken *Token) {
assert(Token->MacroCtx &&
(ActiveExpansions.size() >= Token->MacroCtx->EndOfExpansion));
for (size_t I = 0; I < Token->MacroCtx->EndOfExpansion; ++I) {
#ifndef NDEBUG
// Check all remaining tokens but the final closing parenthesis and optional
// trailing comment were already reconstructed at an inner expansion level.
for (auto T = ActiveExpansions.back().SpelledI;
T != ActiveExpansions.back().SpelledE; ++T) {
FormatToken *Token = T->Tok;
bool ClosingParen = (std::next(T) == ActiveExpansions.back().SpelledE ||
std::next(T)->Tok->isTrailingComment()) &&
!Token->MacroCtx && Token->is(tok::r_paren);
bool TrailingComment = Token->isTrailingComment();
bool PreviousLevel =
Token->MacroCtx &&
(ActiveExpansions.size() < Token->MacroCtx->ExpandedFrom.size());
if (!ClosingParen && !TrailingComment && !PreviousLevel) {
llvm::dbgs() << "At token: " << Token->TokenText << "\n";
}
// In addition to the following cases, we can also run into this
// when a macro call had more arguments than expected; in that case,
// the comma and the remaining tokens in the macro call will potentially
// end up in the line when we finish the expansion.
// FIXME: Add the information which arguments are unused, and assert
// one of the cases below plus reconstructed macro argument tokens.
// assert(ClosingParen || TrailingComment || PreviousLevel);
}
#endif
// Handle the remaining open tokens:
// - expand the closing parenthesis, if it exists, including an optional
// trailing comment
// - handle tokens that were already reconstructed at an inner expansion
// level
// - handle tokens when a macro call had more than the expected number of
// arguments, i.e. when #define M(x) is called as M(a, b, c) we'll end
// up with the sequence ", b, c)" being open at the end of the
// reconstruction; we want to gracefully handle that case
//
// FIXME: See the above debug-check for what we will need to do to be
// able to assert this.
for (auto T = ActiveExpansions.back().SpelledI;
T != ActiveExpansions.back().SpelledE; ++T) {
processNextReconstructed();
}
ActiveExpansions.pop_back();
}
}
void MacroCallReconstructor::debugParentMap() const {
llvm::DenseSet<FormatToken *> Values;
for (const auto &P : SpelledParentToReconstructedParent)
Values.insert(P.second);
for (const auto &P : SpelledParentToReconstructedParent) {
if (Values.contains(P.first))
continue;
llvm::dbgs() << (P.first ? P.first->TokenText : "<null>");
for (auto I = SpelledParentToReconstructedParent.find(P.first),
E = SpelledParentToReconstructedParent.end();
I != E; I = SpelledParentToReconstructedParent.find(I->second)) {
llvm::dbgs() << " -> " << (I->second ? I->second->TokenText : "<null>");
}
llvm::dbgs() << "\n";
}
}
// If visible, add the next token of the reconstructed token sequence to the
// output. Returns whether reconstruction passed a comma that is part of a
// macro call.
bool MacroCallReconstructor::processNextReconstructed() {
FormatToken *Token = ActiveExpansions.back().SpelledI->Tok;
++ActiveExpansions.back().SpelledI;
if (Token->MacroCtx) {
// Skip tokens that are not part of the macro call.
if (Token->MacroCtx->Role == MR_Hidden) {
return false;
}
// Skip tokens we already expanded during an inner reconstruction.
// For example, given: #define ID(x) {x}
// And the call: ID(ID(f))
// We get two reconstructions:
// ID(f) -> {f}
// ID({f}) -> {{f}}
// We reconstruct f during the first reconstruction, and skip it during the
// second reconstruction.
if (ActiveExpansions.size() < Token->MacroCtx->ExpandedFrom.size()) {
return false;
}
}
// Tokens that do not have a macro context are tokens in that are part of the
// macro call that have not taken part in expansion.
if (!Token->MacroCtx) {
// Put the parentheses and commas of a macro call into the same line;
// if the arguments produce new unwrapped lines, they will become children
// of the corresponding opening parenthesis or comma tokens in the
// reconstructed call.
if (Token->is(tok::l_paren)) {
MacroCallStructure.push_back(MacroCallState(
currentLine(), parentLine().Tokens.back()->Tok, Token));
// All tokens that are children of the previous line's last token in the
// reconstructed token stream will now be children of the l_paren token.
// For example, for the line containing the macro calls:
// auto x = ID({ID(2)});
// We will build up a map <null> -> ( -> ( with the first and second
// l_paren of the macro call respectively. New lines that come in with a
// <null> parent will then become children of the l_paren token of the
// currently innermost macro call.
SpelledParentToReconstructedParent[MacroCallStructure.back()
.ParentLastToken] = Token;
appendToken(Token);
prepareParent(Token, /*NewLine=*/true);
Token->MacroParent = true;
return false;
}
if (!MacroCallStructure.empty()) {
if (Token->is(tok::comma)) {
// Make new lines inside the next argument children of the comma token.
SpelledParentToReconstructedParent
[MacroCallStructure.back().Line->Tokens.back()->Tok] = Token;
Token->MacroParent = true;
appendToken(Token, MacroCallStructure.back().Line);
prepareParent(Token, /*NewLine=*/true);
return true;
}
if (Token->is(tok::r_paren)) {
appendToken(Token, MacroCallStructure.back().Line);
SpelledParentToReconstructedParent.erase(
MacroCallStructure.back().ParentLastToken);
MacroCallStructure.pop_back();
return false;
}
}
}
// Note that any tokens that are tagged with MR_None have been passed as
// arguments to the macro that have not been expanded, for example:
// Given: #define ID(X) x
// When calling: ID(a, b)
// 'b' will be part of the reconstructed token stream, but tagged MR_None.
// Given that erroring out in this case would be disruptive, we continue
// pushing the (unformatted) token.
// FIXME: This can lead to unfortunate formatting decisions - give the user
// a hint that their macro definition is broken.
appendToken(Token);
return false;
}
void MacroCallReconstructor::finalize() {
#ifndef NDEBUG
assert(State != Finalized && finished());
State = Finalized;
#endif
// We created corresponding unwrapped lines for each incoming line as children
// the the toplevel null token.
assert(Result.Tokens.size() == 1 && !Result.Tokens.front()->Children.empty());
LLVM_DEBUG({
llvm::dbgs() << "Finalizing reconstructed lines:\n";
debug(Result, 0);
});
// The first line becomes the top level line in the resulting unwrapped line.
LineNode &Top = *Result.Tokens.front();
auto *I = Top.Children.begin();
// Every subsequent line will become a child of the last token in the previous
// line, which is the token prior to the first token in the line.
LineNode *Last = (*I)->Tokens.back().get();
++I;
for (auto *E = Top.Children.end(); I != E; ++I) {
assert(Last->Children.empty());
Last->Children.push_back(std::move(*I));
// Mark the previous line's last token as generated by a macro expansion
// so the formatting algorithm can take that into account.
Last->Tok->MacroParent = true;
Last = Last->Children.back()->Tokens.back().get();
}
Top.Children.resize(1);
}
void MacroCallReconstructor::appendToken(FormatToken *Token,
ReconstructedLine *L) {
L = L ? L : currentLine();
LLVM_DEBUG(llvm::dbgs() << "-> " << Token->TokenText << "\n");
L->Tokens.push_back(std::make_unique<LineNode>(Token));
}
UnwrappedLine
MacroCallReconstructor::createUnwrappedLine(const ReconstructedLine &Line,
int Level) {
UnwrappedLine Result;
Result.Level = Level;
for (const auto &N : Line.Tokens) {
Result.Tokens.push_back(N->Tok);
UnwrappedLineNode &Current = Result.Tokens.back();
for (const auto &Child : N->Children) {
if (Child->Tokens.empty())
continue;
Current.Children.push_back(createUnwrappedLine(*Child, Level + 1));
}
if (Current.Children.size() == 1 &&
Current.Tok->isOneOf(tok::l_paren, tok::comma)) {
Result.Tokens.splice(Result.Tokens.end(),
Current.Children.front().Tokens);
Current.Children.clear();
}
}
return Result;
}
void MacroCallReconstructor::debug(const ReconstructedLine &Line, int Level) {
for (int i = 0; i < Level; ++i)
llvm::dbgs() << " ";
for (const auto &N : Line.Tokens) {
if (!N)
continue;
if (N->Tok)
llvm::dbgs() << N->Tok->TokenText << " ";
for (const auto &Child : N->Children) {
llvm::dbgs() << "\n";
debug(*Child, Level + 1);
for (int i = 0; i < Level; ++i)
llvm::dbgs() << " ";
}
}
llvm::dbgs() << "\n";
}
MacroCallReconstructor::ReconstructedLine &
MacroCallReconstructor::parentLine() {
return **std::prev(std::prev(ActiveReconstructedLines.end()));
}
MacroCallReconstructor::ReconstructedLine *
MacroCallReconstructor::currentLine() {
return ActiveReconstructedLines.back();
}
MacroCallReconstructor::MacroCallState::MacroCallState(
MacroCallReconstructor::ReconstructedLine *Line,
FormatToken *ParentLastToken, FormatToken *MacroCallLParen)
: Line(Line), ParentLastToken(ParentLastToken),
MacroCallLParen(MacroCallLParen) {
LLVM_DEBUG(
llvm::dbgs() << "ParentLastToken: "
<< (ParentLastToken ? ParentLastToken->TokenText : "<null>")
<< "\n");
assert(MacroCallLParen->is(tok::l_paren));
}
} // namespace format
} // namespace clang

View File

@ -1,4 +1,4 @@
//===--- MacroExpander.h - Format C++ code ----------------------*- C++ -*-===//
//===--- Macros.h - Format C++ code -----------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -22,40 +22,38 @@
/// spelled token streams into expanded token streams when it encounters a
/// macro call. The UnwrappedLineParser continues to parse UnwrappedLines
/// from the expanded token stream.
/// After the expanded unwrapped lines are parsed, the MacroUnexpander matches
/// the spelled token stream into unwrapped lines that best resemble the
/// structure of the expanded unwrapped lines.
/// After the expanded unwrapped lines are parsed, the MacroCallReconstructor
/// matches the spelled token stream into unwrapped lines that best resemble the
/// structure of the expanded unwrapped lines. These reconstructed unwrapped
/// lines are aliasing the tokens in the expanded token stream, so that token
/// annotations will be reused when formatting the spelled macro calls.
///
/// When formatting, clang-format formats the expanded unwrapped lines first,
/// determining the token types. Next, it formats the spelled unwrapped lines,
/// keeping the token types fixed, while allowing other formatting decisions
/// to change.
/// When formatting, clang-format annotates and formats the expanded unwrapped
/// lines first, determining the token types. Next, it formats the spelled
/// unwrapped lines, keeping the token types fixed, while allowing other
/// formatting decisions to change.
///
//===----------------------------------------------------------------------===//
#ifndef CLANG_LIB_FORMAT_MACROS_H
#define CLANG_LIB_FORMAT_MACROS_H
#include <list>
#include <map>
#include <string>
#include <unordered_map>
#include <vector>
#include "Encoding.h"
#include "FormatToken.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
namespace llvm {
class MemoryBuffer;
} // namespace llvm
namespace clang {
class IdentifierTable;
class SourceManager;
namespace format {
struct FormatStyle;
struct UnwrappedLine;
struct UnwrappedLineNode;
/// Takes a set of macro definitions as strings and allows expanding calls to
/// those macros.
@ -130,10 +128,253 @@ class MacroExpander {
const FormatStyle &Style;
llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator;
IdentifierTable &IdentTable;
std::vector<std::unique_ptr<llvm::MemoryBuffer>> Buffers;
SmallVector<std::unique_ptr<llvm::MemoryBuffer>> Buffers;
llvm::StringMap<Definition> Definitions;
};
/// Converts a sequence of UnwrappedLines containing expanded macros into a
/// single UnwrappedLine containing the macro calls. This UnwrappedLine may be
/// broken into child lines, in a way that best conveys the structure of the
/// expanded code.
///
/// In the simplest case, a spelled UnwrappedLine contains one macro, and after
/// expanding it we have one expanded UnwrappedLine. In general, macro
/// expansions can span UnwrappedLines, and multiple macros can contribute
/// tokens to the same line. We keep consuming expanded lines until:
/// * all expansions that started have finished (we're not chopping any macros
/// in half)
/// * *and* we've reached the end of a *spelled* unwrapped line.
///
/// A single UnwrappedLine represents this chunk of code.
///
/// After this point, the state of the spelled/expanded stream is "in sync"
/// (both at the start of an UnwrappedLine, with no macros open), so the
/// Unexpander can be thrown away and parsing can continue.
///
/// Given a mapping from the macro name identifier token in the macro call
/// to the tokens of the macro call, for example:
/// CLASSA -> CLASSA({public: void x();})
///
/// When getting the formatted lines of the expansion via the \c addLine method
/// (each '->' specifies a call to \c addLine ):
/// -> class A {
/// -> public:
/// -> void x();
/// -> };
///
/// Creates the tree of unwrapped lines containing the macro call tokens so that
/// the macro call tokens fit the semantic structure of the expanded formatted
/// lines:
/// -> CLASSA({
/// -> public:
/// -> void x();
/// -> })
class MacroCallReconstructor {
public:
/// Create an Reconstructor whose resulting \p UnwrappedLine will start at
/// \p Level, using the map from name identifier token to the corresponding
/// tokens of the spelled macro call.
MacroCallReconstructor(
unsigned Level,
const llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>>
&ActiveExpansions);
/// For the given \p Line, match all occurences of tokens expanded from a
/// macro to unwrapped lines in the spelled macro call so that the resulting
/// tree of unwrapped lines best resembles the structure of unwrapped lines
/// passed in via \c addLine.
void addLine(const UnwrappedLine &Line);
/// Check whether at the current state there is no open macro expansion
/// that needs to be processed to finish an macro call.
/// Only when \c finished() is true, \c takeResult() can be called to retrieve
/// the resulting \c UnwrappedLine.
/// If there are multiple subsequent macro calls within an unwrapped line in
/// the spelled token stream, the calling code may also continue to call
/// \c addLine() when \c finished() is true.
bool finished() const { return ActiveExpansions.empty(); }
/// Retrieve the formatted \c UnwrappedLine containing the orginal
/// macro calls, formatted according to the expanded token stream received
/// via \c addLine().
/// Generally, this line tries to have the same structure as the expanded,
/// formatted unwrapped lines handed in via \c addLine(), with the exception
/// that for multiple top-level lines, each subsequent line will be the
/// child of the last token in its predecessor. This representation is chosen
/// because it is a precondition to the formatter that we get what looks like
/// a single statement in a single \c UnwrappedLine (i.e. matching parens).
///
/// If a token in a macro argument is a child of a token in the expansion,
/// the parent will be the corresponding token in the macro call.
/// For example:
/// #define C(a, b) class C { a b
/// C(int x;, int y;)
/// would expand to
/// class C { int x; int y;
/// where in a formatted line "int x;" and "int y;" would both be new separate
/// lines.
///
/// In the result, "int x;" will be a child of the opening parenthesis in "C("
/// and "int y;" will be a child of the "," token:
/// C (
/// \- int x;
/// ,
/// \- int y;
/// )
UnwrappedLine takeResult() &&;
private:
void add(FormatToken *Token, FormatToken *ExpandedParent, bool First);
void prepareParent(FormatToken *ExpandedParent, bool First);
FormatToken *getParentInResult(FormatToken *Parent);
void reconstruct(FormatToken *Token);
void startReconstruction(FormatToken *Token);
bool reconstructActiveCallUntil(FormatToken *Token);
void endReconstruction(FormatToken *Token);
bool processNextReconstructed();
void finalize();
struct ReconstructedLine;
void appendToken(FormatToken *Token, ReconstructedLine *L = nullptr);
UnwrappedLine createUnwrappedLine(const ReconstructedLine &Line, int Level);
void debug(const ReconstructedLine &Line, int Level);
ReconstructedLine &parentLine();
ReconstructedLine *currentLine();
void debugParentMap() const;
#ifndef NDEBUG
enum ReconstructorState {
Start, // No macro expansion was found in the input yet.
InProgress, // During a macro reconstruction.
Finalized, // Past macro reconstruction, the result is finalized.
};
ReconstructorState State = Start;
#endif
// Node in which we build up the resulting unwrapped line; this type is
// analogous to UnwrappedLineNode.
struct LineNode {
LineNode() = default;
LineNode(FormatToken *Tok) : Tok(Tok) {}
FormatToken *Tok = nullptr;
llvm::SmallVector<std::unique_ptr<ReconstructedLine>> Children;
};
// Line in which we build up the resulting unwrapped line.
// FIXME: Investigate changing UnwrappedLine to a pointer type and using it
// instead of rolling our own type.
struct ReconstructedLine {
llvm::SmallVector<std::unique_ptr<LineNode>> Tokens;
};
// The line in which we collect the resulting reconstructed output.
// To reduce special cases in the algorithm, the first level of the line
// contains a single null token that has the reconstructed incoming
// lines as children.
// In the end, we stich the lines together so that each subsequent line
// is a child of the last token of the previous line. This is necessary
// in order to format the overall expression as a single logical line -
// if we created separate lines, we'd format them with their own top-level
// indent depending on the semantic structure, which is not desired.
ReconstructedLine Result;
// Stack of currently "open" lines, where each line's predecessor's last
// token is the parent token for that line.
llvm::SmallVector<ReconstructedLine *> ActiveReconstructedLines;
// Maps from the expanded token to the token that takes its place in the
// reconstructed token stream in terms of parent-child relationships.
// Note that it might take multiple steps to arrive at the correct
// parent in the output.
// Given: #define C(a, b) []() { a; b; }
// And a call: C(f(), g())
// The structure in the incoming formatted unwrapped line will be:
// []() {
// |- f();
// \- g();
// }
// with f and g being children of the opening brace.
// In the reconstructed call:
// C(f(), g())
// \- f()
// \- g()
// We want f to be a child of the opening parenthesis and g to be a child
// of the comma token in the macro call.
// Thus, we map
// { -> (
// and add
// ( -> ,
// once we're past the comma in the reconstruction.
llvm::DenseMap<FormatToken *, FormatToken *>
SpelledParentToReconstructedParent;
// Keeps track of a single expansion while we're reconstructing tokens it
// generated.
struct Expansion {
// The identifier token of the macro call.
FormatToken *ID;
// Our current position in the reconstruction.
std::list<UnwrappedLineNode>::iterator SpelledI;
// The end of the reconstructed token sequence.
std::list<UnwrappedLineNode>::iterator SpelledE;
};
// Stack of macro calls for which we're in the middle of an expansion.
llvm::SmallVector<Expansion> ActiveExpansions;
struct MacroCallState {
MacroCallState(ReconstructedLine *Line, FormatToken *ParentLastToken,
FormatToken *MacroCallLParen);
ReconstructedLine *Line;
// The last token in the parent line or expansion, or nullptr if the macro
// expansion is on a top-level line.
//
// For example, in the macro call:
// auto f = []() { ID(1); };
// The MacroCallState for ID will have '{' as ParentLastToken.
//
// In the macro call:
// ID(ID(void f()));
// The MacroCallState of the outer ID will have nullptr as ParentLastToken,
// while the MacroCallState for the inner ID will have the '(' of the outer
// ID as ParentLastToken.
//
// In the macro call:
// ID2(a, ID(b));
// The MacroCallState of ID will have ',' as ParentLastToken.
FormatToken *ParentLastToken;
// The l_paren of this MacroCallState's macro call.
FormatToken *MacroCallLParen;
};
// Keeps track of the lines into which the opening brace/parenthesis &
// argument separating commas for each level in the macro call go in order to
// put the corresponding closing brace/parenthesis into the same line in the
// output and keep track of which parents in the expanded token stream map to
// which tokens in the reconstructed stream.
// When an opening brace/parenthesis has children, we want the structure of
// the output line to be:
// |- MACRO
// |- (
// | \- <argument>
// |- ,
// | \- <argument>
// \- )
llvm::SmallVector<MacroCallState> MacroCallStructure;
// Level the generated UnwrappedLine will be at.
const unsigned Level;
// Maps from identifier of the macro call to an unwrapped line containing
// all tokens of the macro call.
const llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>>
&IdToReconstructed;
};
} // namespace format
} // namespace clang

View File

@ -4734,7 +4734,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
// the first list element. Otherwise, it should be placed outside of the
// list.
return Left.is(BK_BracedInit) ||
(Left.is(TT_CtorInitializerColon) &&
(Left.is(TT_CtorInitializerColon) && Right.NewlinesBefore > 0 &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon);
}
if (Left.is(tok::question) && Right.is(tok::colon))
@ -4894,8 +4894,10 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))
return true;
if (Left.is(TT_CtorInitializerColon))
return Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon;
if (Left.is(TT_CtorInitializerColon)) {
return Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon &&
(!Right.isTrailingComment() || Right.NewlinesBefore > 0);
}
if (Right.is(TT_CtorInitializerColon))
return Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon;
if (Left.is(TT_CtorInitializerComma) &&

View File

@ -59,14 +59,12 @@ class LevelIndentTracker {
Offset = getIndentOffset(*Line.First);
// Update the indent level cache size so that we can rely on it
// having the right size in adjustToUnmodifiedline.
while (IndentForLevel.size() <= Line.Level)
IndentForLevel.push_back(-1);
skipLine(Line, /*UnknownIndent=*/true);
if (Line.InPPDirective) {
unsigned IndentWidth =
(Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth;
Indent = Line.Level * IndentWidth + AdditionalIndent;
} else {
IndentForLevel.resize(Line.Level + 1);
Indent = getIndent(Line.Level);
}
if (static_cast<int>(Indent) + Offset >= 0)
@ -77,9 +75,9 @@ class LevelIndentTracker {
/// Update the indent state given that \p Line indent should be
/// skipped.
void skipLine(const AnnotatedLine &Line) {
while (IndentForLevel.size() <= Line.Level)
IndentForLevel.push_back(Indent);
void skipLine(const AnnotatedLine &Line, bool UnknownIndent = false) {
if (Line.Level >= IndentForLevel.size())
IndentForLevel.resize(Line.Level + 1, UnknownIndent ? -1 : Indent);
}
/// Update the level indent to adapt to the given \p Line.
@ -91,6 +89,7 @@ class LevelIndentTracker {
unsigned LevelIndent = Line.First->OriginalColumn;
if (static_cast<int>(LevelIndent) - Offset >= 0)
LevelIndent -= Offset;
assert(Line.Level < IndentForLevel.size());
if ((!Line.First->is(tok::comment) || IndentForLevel[Line.Level] == -1) &&
!Line.InPPDirective) {
IndentForLevel[Line.Level] = LevelIndent;
@ -159,7 +158,7 @@ class LevelIndentTracker {
const unsigned AdditionalIndent;
/// The indent in characters for each level.
std::vector<int> IndentForLevel;
SmallVector<int> IndentForLevel;
/// Offset of the current line relative to the indent level.
///
@ -1133,7 +1132,7 @@ class OptimizingLineFormatter : public LineFormatter {
typedef std::pair<OrderedPenalty, StateNode *> QueueItem;
/// The BFS queue type.
typedef std::priority_queue<QueueItem, std::vector<QueueItem>,
typedef std::priority_queue<QueueItem, SmallVector<QueueItem>,
std::greater<QueueItem>>
QueueType;

View File

@ -15,6 +15,7 @@
#include "UnwrappedLineParser.h"
#include "FormatToken.h"
#include "TokenAnnotator.h"
#include "clang/Basic/TokenKinds.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@ -1910,15 +1911,12 @@ void UnwrappedLineParser::parseStructuralElement(
break;
auto OneTokenSoFar = [&]() {
const UnwrappedLineNode *Tok = &Line->Tokens.front(),
*End = Tok + Line->Tokens.size();
while (Tok != End && Tok->Tok->is(tok::comment))
++Tok;
// In Verilog, macro invocations start with a backtick which the code
// treats as a hash. Skip it.
if (Style.isVerilog() && Tok != End && Tok->Tok->is(tok::hash))
++Tok;
return End - Tok == 1;
auto I = Line->Tokens.begin(), E = Line->Tokens.end();
while (I != E && I->Tok->is(tok::comment))
++I;
while (I != E && Style.isVerilog() && I->Tok->is(tok::hash))
++I;
return I != E && (++I == E);
};
if (OneTokenSoFar()) {
if (FormatTok->is(tok::colon) && !Line->MustBeDeclaration) {

View File

@ -20,6 +20,7 @@
#include "clang/Format/Format.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/Support/Regex.h"
#include <list>
#include <stack>
#include <vector>
@ -38,7 +39,7 @@ struct UnwrappedLine {
UnwrappedLine();
/// The \c Tokens comprising this \c UnwrappedLine.
std::vector<UnwrappedLineNode> Tokens;
std::list<UnwrappedLineNode> Tokens;
/// The indent level of the \c UnwrappedLine.
unsigned Level;

View File

@ -115,9 +115,9 @@ bool CompilerInstance::createTarget() {
auto TO = std::make_shared<TargetOptions>();
TO->Triple = llvm::Triple::normalize(getFrontendOpts().AuxTriple);
if (getFrontendOpts().AuxTargetCPU)
TO->CPU = getFrontendOpts().AuxTargetCPU.getValue();
TO->CPU = getFrontendOpts().AuxTargetCPU.value();
if (getFrontendOpts().AuxTargetFeatures)
TO->FeaturesAsWritten = getFrontendOpts().AuxTargetFeatures.getValue();
TO->FeaturesAsWritten = getFrontendOpts().AuxTargetFeatures.value();
TO->HostTriple = getTarget().getTriple().str();
setAuxTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), TO));
}
@ -757,6 +757,8 @@ void CompilerInstance::createSema(TranslationUnitKind TUKind,
// Output Files
void CompilerInstance::clearOutputFiles(bool EraseFiles) {
// The ASTConsumer can own streams that write to the output files.
assert(!hasASTConsumer() && "ASTConsumer should be reset");
// Ignore errors that occur when trying to discard the temp file.
for (OutputFile &OF : OutputFiles) {
if (EraseFiles) {
@ -1235,8 +1237,7 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
// Execute the action to actually build the module in-place. Use a separate
// thread so that we get a stack large enough.
llvm::CrashRecoveryContext CRC;
CRC.RunSafelyOnThread(
bool Crashed = !llvm::CrashRecoveryContext().RunSafelyOnThread(
[&]() {
GenerateModuleFromModuleMapAction Action;
Instance.ExecuteAction(Action);
@ -1249,9 +1250,15 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
diag::remark_module_build_done)
<< ModuleName;
// Delete any remaining temporary files related to Instance, in case the
// module generation thread crashed.
Instance.clearOutputFiles(/*EraseFiles=*/true);
if (Crashed) {
// Clear the ASTConsumer if it hasn't been already, in case it owns streams
// that must be closed before clearing output files.
Instance.setSema(nullptr);
Instance.setASTConsumer(nullptr);
// Delete any remaining temporary files related to Instance.
Instance.clearOutputFiles(/*EraseFiles=*/true);
}
// If \p AllowPCMWithCompilerErrors is set return 'success' even if errors
// occurred.

View File

@ -1485,6 +1485,9 @@ void CompilerInvocation::GenerateCodeGenArgs(
if (Opts.IBTSeal)
GenerateArg(Args, OPT_mibt_seal, SA);
if (Opts.FunctionReturnThunks)
GenerateArg(Args, OPT_mfunction_return_EQ, "thunk-extern", SA);
for (const auto &F : Opts.LinkBitcodeFiles) {
bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded &&
F.PropagateAttrs && F.Internalize;
@ -1825,6 +1828,27 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
}
if (const Arg *A = Args.getLastArg(OPT_mfunction_return_EQ)) {
auto Val = llvm::StringSwitch<llvm::FunctionReturnThunksKind>(A->getValue())
.Case("keep", llvm::FunctionReturnThunksKind::Keep)
.Case("thunk-extern", llvm::FunctionReturnThunksKind::Extern)
.Default(llvm::FunctionReturnThunksKind::Invalid);
// SystemZ might want to add support for "expolines."
if (!T.isX86())
Diags.Report(diag::err_drv_argument_not_allowed_with)
<< A->getSpelling() << T.getTriple();
else if (Val == llvm::FunctionReturnThunksKind::Invalid)
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
else if (Val == llvm::FunctionReturnThunksKind::Extern &&
Args.getLastArgValue(OPT_mcmodel_EQ).equals("large"))
Diags.Report(diag::err_drv_argument_not_allowed_with)
<< A->getAsString(Args)
<< Args.getLastArg(OPT_mcmodel_EQ)->getAsString(Args);
else
Opts.FunctionReturnThunks = static_cast<unsigned>(Val);
}
if (Opts.PrepareForLTO && Args.hasArg(OPT_mibt_seal))
Opts.IBTSeal = 1;
@ -1952,7 +1976,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
} else {
Opts.DiagnosticsHotnessThreshold = *ResultOrErr;
if ((!Opts.DiagnosticsHotnessThreshold ||
Opts.DiagnosticsHotnessThreshold.getValue() > 0) &&
Opts.DiagnosticsHotnessThreshold.value() > 0) &&
!UsingProfile)
Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
<< "-fdiagnostics-hotness-threshold=";
@ -1969,7 +1993,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
} else {
Opts.DiagnosticsMisExpectTolerance = *ResultOrErr;
if ((!Opts.DiagnosticsMisExpectTolerance ||
Opts.DiagnosticsMisExpectTolerance.getValue() > 0) &&
Opts.DiagnosticsMisExpectTolerance.value() > 0) &&
!UsingProfile)
Diags.Report(diag::warn_drv_diagnostics_misexpect_requires_pgo)
<< "-fdiagnostics-misexpect-tolerance=";

View File

@ -24,6 +24,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Sema/HLSLExternalSemaSource.h"
#include "clang/Serialization/ASTDeserializationListener.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
@ -580,6 +581,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
auto FailureCleanup = llvm::make_scope_exit([&]() {
if (HasBegunSourceFile)
CI.getDiagnosticClient().EndSourceFile();
CI.setASTConsumer(nullptr);
CI.clearOutputFiles(/*EraseFiles=*/true);
CI.getLangOpts().setCompilingModule(LangOptions::CMK_None);
setCurrentInput(FrontendInputFile());
@ -1014,6 +1016,13 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
CI.getASTContext().setExternalSource(Override);
}
// Setup HLSL External Sema Source
if (CI.getLangOpts().HLSL && CI.hasASTContext()) {
IntrusiveRefCntPtr<ExternalASTSource> HLSLSema(
new HLSLExternalSemaSource());
CI.getASTContext().setExternalSource(HLSLSema);
}
FailureCleanup.release();
return true;
}

View File

@ -854,8 +854,9 @@ void DumpModuleInfoAction::ExecuteAction() {
std::error_code EC;
OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str(), EC,
llvm::sys::fs::OF_TextWithCRLF));
OutputStream = OutFile.get();
}
llvm::raw_ostream &Out = OutFile.get()? *OutFile.get() : llvm::outs();
llvm::raw_ostream &Out = OutputStream ? *OutputStream : llvm::outs();
Out << "Information for module file '" << getCurrentFile() << "':\n";
auto &FileMgr = getCompilerInstance().getFileManager();

View File

@ -832,11 +832,11 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
unsigned minor = 0;
if (tuple.getMinor())
minor = tuple.getMinor().getValue();
minor = tuple.getMinor().value();
unsigned subminor = 0;
if (tuple.getSubminor())
subminor = tuple.getSubminor().getValue();
subminor = tuple.getSubminor().value();
Builder.defineMacro("__OBJFW_RUNTIME_ABI__",
Twine(tuple.getMajor() * 10000 + minor * 100 +

View File

@ -27,38 +27,38 @@ typedef long int64_t;
// built-in vector data types:
#ifdef __HLSL_ENABLE_16_BIT
typedef int16_t int16_t2 __attribute__((ext_vector_type(2)));
typedef int16_t int16_t3 __attribute__((ext_vector_type(3)));
typedef int16_t int16_t4 __attribute__((ext_vector_type(4)));
typedef uint16_t uint16_t2 __attribute__((ext_vector_type(2)));
typedef uint16_t uint16_t3 __attribute__((ext_vector_type(3)));
typedef uint16_t uint16_t4 __attribute__((ext_vector_type(4)));
typedef vector<int16_t, 2> int16_t2;
typedef vector<int16_t, 3> int16_t3;
typedef vector<int16_t, 4> int16_t4;
typedef vector<uint16_t, 2> uint16_t2;
typedef vector<uint16_t, 3> uint16_t3;
typedef vector<uint16_t, 4> uint16_t4;
#endif
typedef int int2 __attribute__((ext_vector_type(2)));
typedef int int3 __attribute__((ext_vector_type(3)));
typedef int int4 __attribute__((ext_vector_type(4)));
typedef uint uint2 __attribute__((ext_vector_type(2)));
typedef uint uint3 __attribute__((ext_vector_type(3)));
typedef uint uint4 __attribute__((ext_vector_type(4)));
typedef int64_t int64_t2 __attribute__((ext_vector_type(2)));
typedef int64_t int64_t3 __attribute__((ext_vector_type(3)));
typedef int64_t int64_t4 __attribute__((ext_vector_type(4)));
typedef uint64_t uint64_t2 __attribute__((ext_vector_type(2)));
typedef uint64_t uint64_t3 __attribute__((ext_vector_type(3)));
typedef uint64_t uint64_t4 __attribute__((ext_vector_type(4)));
typedef vector<int, 2> int2;
typedef vector<int, 3> int3;
typedef vector<int, 4> int4;
typedef vector<uint, 2> uint2;
typedef vector<uint, 3> uint3;
typedef vector<uint, 4> uint4;
typedef vector<int64_t, 2> int64_t2;
typedef vector<int64_t, 3> int64_t3;
typedef vector<int64_t, 4> int64_t4;
typedef vector<uint64_t, 2> uint64_t2;
typedef vector<uint64_t, 3> uint64_t3;
typedef vector<uint64_t, 4> uint64_t4;
#ifdef __HLSL_ENABLE_16_BIT
typedef half half2 __attribute__((ext_vector_type(2)));
typedef half half3 __attribute__((ext_vector_type(3)));
typedef half half4 __attribute__((ext_vector_type(4)));
typedef vector<half, 2> half2;
typedef vector<half, 3> half3;
typedef vector<half, 4> half4;
#endif
typedef float float2 __attribute__((ext_vector_type(2)));
typedef float float3 __attribute__((ext_vector_type(3)));
typedef float float4 __attribute__((ext_vector_type(4)));
typedef double double2 __attribute__((ext_vector_type(2)));
typedef double double3 __attribute__((ext_vector_type(3)));
typedef double double4 __attribute__((ext_vector_type(4)));
typedef vector<float, 2> float2;
typedef vector<float, 3> float3;
typedef vector<float, 4> float4;
typedef vector<double, 2> double2;
typedef vector<double, 3> double3;
typedef vector<double, 4> double4;
#endif //_HLSL_HLSL_BASIC_TYPES_H_

View File

@ -10467,12 +10467,6 @@ float __ovld __cnfn fast_distance(float, float);
float __ovld __cnfn fast_distance(float2, float2);
float __ovld __cnfn fast_distance(float3, float3);
float __ovld __cnfn fast_distance(float4, float4);
#ifdef cl_khr_fp16
half __ovld __cnfn fast_distance(half, half);
half __ovld __cnfn fast_distance(half2, half2);
half __ovld __cnfn fast_distance(half3, half3);
half __ovld __cnfn fast_distance(half4, half4);
#endif //cl_khr_fp16
/**
* Returns the length of vector p computed as:
@ -10482,12 +10476,6 @@ float __ovld __cnfn fast_length(float);
float __ovld __cnfn fast_length(float2);
float __ovld __cnfn fast_length(float3);
float __ovld __cnfn fast_length(float4);
#ifdef cl_khr_fp16
half __ovld __cnfn fast_length(half);
half __ovld __cnfn fast_length(half2);
half __ovld __cnfn fast_length(half3);
half __ovld __cnfn fast_length(half4);
#endif //cl_khr_fp16
/**
* Returns a vector in the same direction as p but with a
@ -10514,12 +10502,6 @@ float __ovld __cnfn fast_normalize(float);
float2 __ovld __cnfn fast_normalize(float2);
float3 __ovld __cnfn fast_normalize(float3);
float4 __ovld __cnfn fast_normalize(float4);
#ifdef cl_khr_fp16
half __ovld __cnfn fast_normalize(half);
half2 __ovld __cnfn fast_normalize(half2);
half3 __ovld __cnfn fast_normalize(half3);
half4 __ovld __cnfn fast_normalize(half4);
#endif //cl_khr_fp16
// OpenCL v1.1 s6.11.6, v1.2 s6.12.6, v2.0 s6.13.6 - Relational Functions

View File

@ -0,0 +1,57 @@
/*===---- rdpruintrin.h - RDPRU intrinsics ---------------------------------===
*
* 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
*
*===-----------------------------------------------------------------------===
*/
#if !defined __X86INTRIN_H
#error "Never use <rdpruintrin.h> directly; include <x86intrin.h> instead."
#endif
#ifndef __RDPRUINTRIN_H
#define __RDPRUINTRIN_H
/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, __target__("rdpru")))
/// Reads the content of a processor register.
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> RDPRU </c> instruction.
///
/// \param reg_id
/// A processor register identifier.
static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__rdpru (int reg_id)
{
return __builtin_ia32_rdpru(reg_id);
}
#define __RDPRU_MPERF 0
#define __RDPRU_APERF 1
/// Reads the content of processor register MPERF.
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic generates instruction <c> RDPRU </c> to read the value of
/// register MPERF.
#define __mperf() __builtin_ia32_rdpru(__RDPRU_MPERF)
/// Reads the content of processor register APERF.
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic generates instruction <c> RDPRU </c> to read the value of
/// register APERF.
#define __aperf() __builtin_ia32_rdpru(__RDPRU_APERF)
#undef __DEFAULT_FN_ATTRS
#endif /* __RDPRUINTRIN_H */

View File

@ -158,10 +158,6 @@ typedef _Atomic(uintmax_t) atomic_uintmax_t;
typedef struct atomic_flag { atomic_bool _Value; } atomic_flag;
#define ATOMIC_FLAG_INIT { 0 }
#if __cplusplus >= 202002L && !defined(_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS)
/* ATOMIC_FLAG_INIT was deprecated in C++20 but is not deprecated in C. */
#pragma clang deprecated(ATOMIC_FLAG_INIT)
#endif
/* These should be provided by the libc implementation. */
#ifdef __cplusplus

View File

@ -59,5 +59,9 @@
#include <clzerointrin.h>
#endif
#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \
defined(__RDPRU__)
#include <rdpruintrin.h>
#endif
#endif /* __X86INTRIN_H */

View File

@ -550,7 +550,7 @@ Scanner::tryLexIdentifierOrSkipLine(const char *&First, const char *const End) {
StringRef Scanner::lexIdentifier(const char *&First, const char *const End) {
Optional<StringRef> Id = tryLexIdentifierOrSkipLine(First, End);
assert(Id && "expected identifier token");
return Id.getValue();
return Id.value();
}
bool Scanner::isNextIdentifierOrSkipLine(StringRef Id, const char *&First,

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