30 changes: 26 additions & 4 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -3663,14 +3663,14 @@ defm rwpi : BoolFOption<"rwpi",
"Generate read-write position independent code (ARM only)">,
NegFlag<SetFalse, [], [ClangOption, FlangOption, CC1Option]>>;
def fplugin_EQ : Joined<["-"], "fplugin=">, Group<f_Group>,
Flags<[NoXarchOption]>, MetaVarName<"<dsopath>">,
Flags<[NoXarchOption, NoArgumentUnused]>, MetaVarName<"<dsopath>">,
HelpText<"Load the named plugin (dynamic shared object)">;
def fplugin_arg : Joined<["-"], "fplugin-arg-">,
MetaVarName<"<name>-<arg>">,
MetaVarName<"<name>-<arg>">, Flags<[NoArgumentUnused]>,
HelpText<"Pass <arg> to plugin <name>">;
def fpass_plugin_EQ : Joined<["-"], "fpass-plugin=">,
Group<f_Group>, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
MetaVarName<"<dsopath>">,
MetaVarName<"<dsopath>">, Flags<[NoArgumentUnused]>,
HelpText<"Load pass plugin from a dynamic shared object file (only with new pass manager).">,
MarshallingInfoStringVector<CodeGenOpts<"PassPlugins">>;
defm tocdata : BoolOption<"m","tocdata",
Expand Down Expand Up @@ -4159,6 +4159,11 @@ defm unique_section_names : BoolFOption<"unique-section-names",
NegFlag<SetFalse, [], [ClangOption, CC1Option],
"Don't use unique names for text and data sections">,
PosFlag<SetTrue>>;
defm separate_named_sections : BoolFOption<"separate-named-sections",
CodeGenOpts<"SeparateNamedSections">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option],
"Use separate unique sections for named sections (ELF Only)">,
NegFlag<SetFalse>>;

defm split_machine_functions: BoolFOption<"split-machine-functions",
CodeGenOpts<"SplitMachineFunctions">, DefaultFalse,
Expand All @@ -4175,6 +4180,14 @@ defm strict_return : BoolFOption<"strict-return",

let Flags = [TargetSpecific] in {
defm ptrauth_intrinsics : OptInCC1FFlag<"ptrauth-intrinsics", "Enable pointer authentication intrinsics">;
defm ptrauth_calls : OptInCC1FFlag<"ptrauth-calls", "Enable signing and authentication of all indirect calls">;
defm ptrauth_returns : OptInCC1FFlag<"ptrauth-returns", "Enable signing and authentication of return addresses">;
defm ptrauth_auth_traps : OptInCC1FFlag<"ptrauth-auth-traps", "Enable traps on authentication failures">;
defm ptrauth_vtable_pointer_address_discrimination :
OptInCC1FFlag<"ptrauth-vtable-pointer-address-discrimination", "Enable address discrimination of vtable pointers">;
defm ptrauth_vtable_pointer_type_discrimination :
OptInCC1FFlag<"ptrauth-vtable-pointer-type-discrimination", "Enable type discrimination of vtable pointers">;
defm ptrauth_init_fini : OptInCC1FFlag<"ptrauth-init-fini", "Enable signing of function pointers in init/fini arrays">;
}

def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
Expand Down Expand Up @@ -5072,6 +5085,10 @@ def maix_small_local_dynamic_tls : Flag<["-"], "maix-small-local-dynamic-tls">,
"where the offset from the TLS base is encoded as an "
"immediate operand (AIX 64-bit only). "
"This access sequence is not used for variables larger than 32KB.">;
def maix_shared_lib_tls_model_opt : Flag<["-"], "maix-shared-lib-tls-model-opt">,
Group<m_ppc_Features_Group>,
HelpText<"For shared library loaded with the main program, change local-dynamic access(es) "
"to initial-exec access(es) at the function level (AIX 64-bit only).">;
def maix_struct_return : Flag<["-"], "maix-struct-return">,
Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
HelpText<"Return all structs in memory (PPC32 only)">,
Expand Down Expand Up @@ -5698,7 +5715,7 @@ def whatsloaded : Flag<["-"], "whatsloaded">;
def why_load : Flag<["-"], "why_load">;
def whyload : Flag<["-"], "whyload">, Alias<why_load>;
def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">,
Visibility<[ClangOption, CC1Option]>,
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
MarshallingInfoFlag<DiagnosticOpts<"IgnoreWarnings">>;
def x : JoinedOrSeparate<["-"], "x">,
Flags<[NoXarchOption]>,
Expand Down Expand Up @@ -7087,6 +7104,11 @@ def mlink_bitcode_file : Separate<["-"], "mlink-bitcode-file">,
def mlink_builtin_bitcode : Separate<["-"], "mlink-builtin-bitcode">,
HelpText<"Link and internalize needed symbols from the given bitcode file "
"before performing optimizations.">;
defm link_builtin_bitcode_postopt: BoolMOption<"link-builtin-bitcode-postopt",
CodeGenOpts<"LinkBitcodePostopt">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Link builtin bitcodes after the "
"optimization pipeline">,
NegFlag<SetFalse, [], [ClangOption]>>;
def vectorize_loops : Flag<["-"], "vectorize-loops">,
HelpText<"Run the Loop vectorization passes">,
MarshallingInfoFlag<CodeGenOpts<"VectorizeLoop">>;
Expand Down
40 changes: 37 additions & 3 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,8 +375,25 @@ struct FormatStyle {
/// }
/// \endcode
bool AcrossComments;
/// Whether aligned case labels are aligned on the colon, or on the
/// , or on the tokens after the colon.
/// Whether to align the case arrows when aligning short case expressions.
/// \code{.java}
/// true:
/// i = switch (day) {
/// case THURSDAY, SATURDAY -> 8;
/// case WEDNESDAY -> 9;
/// default -> 0;
/// };
///
/// false:
/// i = switch (day) {
/// case THURSDAY, SATURDAY -> 8;
/// case WEDNESDAY -> 9;
/// default -> 0;
/// };
/// \endcode
bool AlignCaseArrows;
/// Whether aligned case labels are aligned on the colon, or on the tokens
/// after the colon.
/// \code
/// true:
/// switch (level) {
Expand All @@ -396,12 +413,14 @@ struct FormatStyle {
bool operator==(const ShortCaseStatementsAlignmentStyle &R) const {
return Enabled == R.Enabled && AcrossEmptyLines == R.AcrossEmptyLines &&
AcrossComments == R.AcrossComments &&
AlignCaseArrows == R.AlignCaseArrows &&
AlignCaseColons == R.AlignCaseColons;
}
};

/// Style of aligning consecutive short case labels.
/// Only applies if ``AllowShortCaseLabelsOnASingleLine`` is ``true``.
/// Only applies if ``AllowShortCaseExpressionOnASingleLine`` or
/// ``AllowShortCaseLabelsOnASingleLine`` is ``true``.
///
/// \code{.yaml}
/// # Example of usage:
Expand Down Expand Up @@ -724,6 +743,19 @@ struct FormatStyle {
/// \version 3.5
ShortBlockStyle AllowShortBlocksOnASingleLine;

/// Whether to merge a short switch labeled rule into a single line.
/// \code{.java}
/// true: false:
/// switch (a) { vs. switch (a) {
/// case 1 -> 1; case 1 ->
/// default -> 0; 1;
/// }; default ->
/// 0;
/// };
/// \endcode
/// \version 19
bool AllowShortCaseExpressionOnASingleLine;

/// If ``true``, short case labels will be contracted to a single line.
/// \code
/// true: false:
Expand Down Expand Up @@ -4923,6 +4955,8 @@ struct FormatStyle {
AllowBreakBeforeNoexceptSpecifier ==
R.AllowBreakBeforeNoexceptSpecifier &&
AllowShortBlocksOnASingleLine == R.AllowShortBlocksOnASingleLine &&
AllowShortCaseExpressionOnASingleLine ==
R.AllowShortCaseExpressionOnASingleLine &&
AllowShortCaseLabelsOnASingleLine ==
R.AllowShortCaseLabelsOnASingleLine &&
AllowShortCompoundRequirementOnASingleLine ==
Expand Down
14 changes: 12 additions & 2 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -3632,6 +3632,13 @@ class Parser : public CodeCompletionHandler {
// Wait constructs, we likely want to put that information in here as well.
};

struct OpenACCWaitParseInfo {
bool Failed = false;
Expr *DevNumExpr = nullptr;
SourceLocation QueuesLoc;
SmallVector<Expr *> QueueIdExprs;
};

/// Represents the 'error' state of parsing an OpenACC Clause, and stores
/// whether we can continue parsing, or should give up on the directive.
enum class OpenACCParseCanContinue { Cannot = 0, Can = 1 };
Expand Down Expand Up @@ -3674,7 +3681,8 @@ class Parser : public CodeCompletionHandler {
/// Parses the clause-list for an OpenACC directive.
SmallVector<OpenACCClause *>
ParseOpenACCClauseList(OpenACCDirectiveKind DirKind);
bool ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective);
OpenACCWaitParseInfo ParseOpenACCWaitArgument(SourceLocation Loc,
bool IsDirective);
/// Parses the clause of the 'bind' argument, which can be a string literal or
/// an ID expression.
ExprResult ParseOpenACCBindClauseArgument();
Expand All @@ -3698,7 +3706,9 @@ class Parser : public CodeCompletionHandler {
bool ParseOpenACCDeviceTypeList();
/// Parses the 'async-argument', which is an integral value with two
/// 'special' values that are likely negative (but come from Macros).
ExprResult ParseOpenACCAsyncArgument();
OpenACCIntExprParseResult ParseOpenACCAsyncArgument(OpenACCDirectiveKind DK,
OpenACCClauseKind CK,
SourceLocation Loc);
/// Parses the 'size-expr', which is an integral value, or an asterisk.
bool ParseOpenACCSizeExpr();
/// Parses a comma delimited list of 'size-expr's.
Expand Down
7 changes: 6 additions & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -9739,6 +9739,9 @@ class Sema final : public SemaBase {
const PartialDiagnostic &CandidateDiag,
bool Complain = true, QualType TargetType = QualType());

FunctionDecl *getMoreConstrainedFunction(FunctionDecl *FD1,
FunctionDecl *FD2);

///@}

//
Expand Down Expand Up @@ -10199,7 +10202,9 @@ class Sema final : public SemaBase {
S.ExprEvalContexts.back().InImmediateFunctionContext =
FD->isImmediateFunction() ||
S.ExprEvalContexts[S.ExprEvalContexts.size() - 2]
.isConstantEvaluated();
.isConstantEvaluated() ||
S.ExprEvalContexts[S.ExprEvalContexts.size() - 2]
.isImmediateFunctionContext();
S.ExprEvalContexts.back().InImmediateEscalatingFunctionContext =
S.getLangOpts().CPlusPlus20 && FD->isImmediateEscalating();
} else
Expand Down
66 changes: 65 additions & 1 deletion clang/include/clang/Sema/SemaOpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,14 @@ class SemaOpenACC : public SemaBase {
bool IsZero;
};

struct WaitDetails {
Expr *DevNumExpr;
SourceLocation QueuesLoc;
SmallVector<Expr *> QueueIdExprs;
};

std::variant<std::monostate, DefaultDetails, ConditionDetails,
IntExprDetails, VarListDetails>
IntExprDetails, VarListDetails, WaitDetails>
Details = std::monostate{};

public:
Expand Down Expand Up @@ -101,16 +107,55 @@ class SemaOpenACC : public SemaBase {
unsigned getNumIntExprs() const {
assert((ClauseKind == OpenACCClauseKind::NumGangs ||
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::Async ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");

// 'async' and 'wait' have an optional IntExpr, so be tolerant of that.
if ((ClauseKind == OpenACCClauseKind::Async ||
ClauseKind == OpenACCClauseKind::Wait) &&
std::holds_alternative<std::monostate>(Details))
return 0;
return std::get<IntExprDetails>(Details).IntExprs.size();
}

SourceLocation getQueuesLoc() const {
assert(ClauseKind == OpenACCClauseKind::Wait &&
"Parsed clause kind does not have a queues location");

if (std::holds_alternative<std::monostate>(Details))
return SourceLocation{};

return std::get<WaitDetails>(Details).QueuesLoc;
}

Expr *getDevNumExpr() const {
assert(ClauseKind == OpenACCClauseKind::Wait &&
"Parsed clause kind does not have a device number expr");

if (std::holds_alternative<std::monostate>(Details))
return nullptr;

return std::get<WaitDetails>(Details).DevNumExpr;
}

ArrayRef<Expr *> getQueueIdExprs() const {
assert(ClauseKind == OpenACCClauseKind::Wait &&
"Parsed clause kind does not have a queue id expr list");

if (std::holds_alternative<std::monostate>(Details))
return ArrayRef<Expr *>{std::nullopt};

return std::get<WaitDetails>(Details).QueueIdExprs;
}

ArrayRef<Expr *> getIntExprs() {
assert((ClauseKind == OpenACCClauseKind::NumGangs ||
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::Async ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");

return std::get<IntExprDetails>(Details).IntExprs;
}

Expand All @@ -134,6 +179,8 @@ class SemaOpenACC : public SemaBase {
ClauseKind == OpenACCClauseKind::Create ||
ClauseKind == OpenACCClauseKind::PCreate ||
ClauseKind == OpenACCClauseKind::PresentOrCreate ||
ClauseKind == OpenACCClauseKind::Attach ||
ClauseKind == OpenACCClauseKind::DevicePtr ||
ClauseKind == OpenACCClauseKind::FirstPrivate) &&
"Parsed clause kind does not have a var-list");
return std::get<VarListDetails>(Details).VarList;
Expand Down Expand Up @@ -188,13 +235,15 @@ class SemaOpenACC : public SemaBase {
void setIntExprDetails(ArrayRef<Expr *> IntExprs) {
assert((ClauseKind == OpenACCClauseKind::NumGangs ||
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::Async ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");
Details = IntExprDetails{{IntExprs.begin(), IntExprs.end()}};
}
void setIntExprDetails(llvm::SmallVector<Expr *> &&IntExprs) {
assert((ClauseKind == OpenACCClauseKind::NumGangs ||
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::Async ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");
Details = IntExprDetails{std::move(IntExprs)};
Expand All @@ -217,6 +266,8 @@ class SemaOpenACC : public SemaBase {
ClauseKind == OpenACCClauseKind::Create ||
ClauseKind == OpenACCClauseKind::PCreate ||
ClauseKind == OpenACCClauseKind::PresentOrCreate ||
ClauseKind == OpenACCClauseKind::Attach ||
ClauseKind == OpenACCClauseKind::DevicePtr ||
ClauseKind == OpenACCClauseKind::FirstPrivate) &&
"Parsed clause kind does not have a var-list");
assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
Expand Down Expand Up @@ -251,6 +302,8 @@ class SemaOpenACC : public SemaBase {
ClauseKind == OpenACCClauseKind::Create ||
ClauseKind == OpenACCClauseKind::PCreate ||
ClauseKind == OpenACCClauseKind::PresentOrCreate ||
ClauseKind == OpenACCClauseKind::Attach ||
ClauseKind == OpenACCClauseKind::DevicePtr ||
ClauseKind == OpenACCClauseKind::FirstPrivate) &&
"Parsed clause kind does not have a var-list");
assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
Expand All @@ -266,6 +319,13 @@ class SemaOpenACC : public SemaBase {
"zero: tag only valid on copyout/create");
Details = VarListDetails{std::move(VarList), IsReadOnly, IsZero};
}

void setWaitDetails(Expr *DevNum, SourceLocation QueuesLoc,
llvm::SmallVector<Expr *> &&IntExprs) {
assert(ClauseKind == OpenACCClauseKind::Wait &&
"Parsed clause kind does not have a wait-details");
Details = WaitDetails{DevNum, QueuesLoc, std::move(IntExprs)};
}
};

SemaOpenACC(Sema &S);
Expand Down Expand Up @@ -315,6 +375,10 @@ class SemaOpenACC : public SemaBase {
/// declaration reference to a variable of the correct type.
ExprResult ActOnVar(Expr *VarExpr);

/// Called to check the 'var' type is a variable of pointer type, necessary
/// for 'deviceptr' and 'attach' clauses. Returns true on success.
bool CheckVarIsPointerType(OpenACCClauseKind ClauseKind, Expr *VarExpr);

/// Checks and creates an Array Section used in an OpenACC construct/clause.
ExprResult ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc,
Expr *LowerBound,
Expand Down
122 changes: 61 additions & 61 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Serialization/SourceLocationEncoding.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Bitstream/BitCodes.h"
#include <cassert>
Expand Down Expand Up @@ -165,99 +166,95 @@ using SubmoduleID = uint32_t;
/// The number of predefined submodule IDs.
const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1;

/// 32 aligned uint64_t in the AST file. Use splitted 64-bit integer into
/// low/high parts to keep structure alignment 32-bit (it is important
/// because blobs in bitstream are 32-bit aligned). This structure is
/// serialized "as is" to the AST file.
class UnalignedUInt64 {
uint32_t BitLow = 0;
uint32_t BitHigh = 0;

public:
UnalignedUInt64() = default;
UnalignedUInt64(uint64_t BitOffset) { set(BitOffset); }

void set(uint64_t Offset) {
BitLow = Offset;
BitHigh = Offset >> 32;
}

uint64_t get() const { return BitLow | (uint64_t(BitHigh) << 32); }
};

/// Source range/offset of a preprocessed entity.
struct PPEntityOffset {
class PPEntityOffset {
using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;

/// Raw source location of beginning of range.
SourceLocation::UIntTy Begin;
UnalignedUInt64 Begin;

/// Raw source location of end of range.
SourceLocation::UIntTy End;
UnalignedUInt64 End;

/// Offset in the AST file relative to ModuleFile::MacroOffsetsBase.
uint32_t BitOffset;

PPEntityOffset(SourceRange R, uint32_t BitOffset)
: Begin(R.getBegin().getRawEncoding()), End(R.getEnd().getRawEncoding()),
BitOffset(BitOffset) {}
public:
PPEntityOffset(RawLocEncoding Begin, RawLocEncoding End, uint32_t BitOffset)
: Begin(Begin), End(End), BitOffset(BitOffset) {}

SourceLocation getBegin() const {
return SourceLocation::getFromRawEncoding(Begin);
}
RawLocEncoding getBegin() const { return Begin.get(); }
RawLocEncoding getEnd() const { return End.get(); }

SourceLocation getEnd() const {
return SourceLocation::getFromRawEncoding(End);
}
uint32_t getOffset() const { return BitOffset; }
};

/// Source range of a skipped preprocessor region
struct PPSkippedRange {
class PPSkippedRange {
using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;

/// Raw source location of beginning of range.
SourceLocation::UIntTy Begin;
UnalignedUInt64 Begin;
/// Raw source location of end of range.
SourceLocation::UIntTy End;
UnalignedUInt64 End;

PPSkippedRange(SourceRange R)
: Begin(R.getBegin().getRawEncoding()), End(R.getEnd().getRawEncoding()) {
}
public:
PPSkippedRange(RawLocEncoding Begin, RawLocEncoding End)
: Begin(Begin), End(End) {}

SourceLocation getBegin() const {
return SourceLocation::getFromRawEncoding(Begin);
}
SourceLocation getEnd() const {
return SourceLocation::getFromRawEncoding(End);
}
RawLocEncoding getBegin() const { return Begin.get(); }
RawLocEncoding getEnd() const { return End.get(); }
};

/// Offset in the AST file. Use splitted 64-bit integer into low/high
/// parts to keep structure alignment 32-bit (it is important because
/// blobs in bitstream are 32-bit aligned). This structure is serialized
/// "as is" to the AST file.
struct UnderalignedInt64 {
uint32_t BitOffsetLow = 0;
uint32_t BitOffsetHigh = 0;

UnderalignedInt64() = default;
UnderalignedInt64(uint64_t BitOffset) { setBitOffset(BitOffset); }

void setBitOffset(uint64_t Offset) {
BitOffsetLow = Offset;
BitOffsetHigh = Offset >> 32;
}

uint64_t getBitOffset() const {
return BitOffsetLow | (uint64_t(BitOffsetHigh) << 32);
}
};
/// Source location and bit offset of a declaration. Keep
/// structure alignment 32-bit since the blob is assumed as 32-bit aligned.
class DeclOffset {
using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;

/// Source location and bit offset of a declaration.
struct DeclOffset {
/// Raw source location.
SourceLocation::UIntTy Loc = 0;
UnalignedUInt64 RawLoc;

/// Offset relative to the start of the DECLTYPES_BLOCK block. Keep
/// structure alignment 32-bit and avoid padding gap because undefined
/// value in the padding affects AST hash.
UnderalignedInt64 BitOffset;
/// Offset relative to the start of the DECLTYPES_BLOCK block.
UnalignedUInt64 BitOffset;

public:
DeclOffset() = default;
DeclOffset(SourceLocation Loc, uint64_t BitOffset,
uint64_t DeclTypesBlockStartOffset) {
setLocation(Loc);
DeclOffset(RawLocEncoding RawLoc, uint64_t BitOffset,
uint64_t DeclTypesBlockStartOffset)
: RawLoc(RawLoc) {
setBitOffset(BitOffset, DeclTypesBlockStartOffset);
}

void setLocation(SourceLocation L) { Loc = L.getRawEncoding(); }
void setRawLoc(RawLocEncoding Loc) { RawLoc = Loc; }

SourceLocation getLocation() const {
return SourceLocation::getFromRawEncoding(Loc);
}
RawLocEncoding getRawLoc() const { return RawLoc.get(); }

void setBitOffset(uint64_t Offset, const uint64_t DeclTypesBlockStartOffset) {
BitOffset.setBitOffset(Offset - DeclTypesBlockStartOffset);
BitOffset.set(Offset - DeclTypesBlockStartOffset);
}

uint64_t getBitOffset(const uint64_t DeclTypesBlockStartOffset) const {
return BitOffset.getBitOffset() + DeclTypesBlockStartOffset;
return BitOffset.get() + DeclTypesBlockStartOffset;
}
};

Expand Down Expand Up @@ -1091,6 +1088,9 @@ enum PredefinedTypeIDs {
// \brief WebAssembly reference types with auto numeration
#define WASM_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID,
#include "clang/Basic/WebAssemblyReferenceTypes.def"

/// The placeholder type for unresolved templates.
PREDEF_TYPE_UNRESOLVED_TEMPLATE,
// Sentinel value. Considered a predefined type but not useable as one.
PREDEF_TYPE_LAST_ID
};
Expand All @@ -1100,7 +1100,7 @@ enum PredefinedTypeIDs {
///
/// Type IDs for non-predefined types will start at
/// NUM_PREDEF_TYPE_IDs.
const unsigned NUM_PREDEF_TYPE_IDS = 502;
const unsigned NUM_PREDEF_TYPE_IDS = 503;

// Ensure we do not overrun the predefined types we reserved
// in the enum PredefinedTypeIDs above.
Expand Down
48 changes: 31 additions & 17 deletions clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -1771,6 +1771,7 @@ class ASTReader

/// Retrieve the module manager.
ModuleManager &getModuleManager() { return ModuleMgr; }
const ModuleManager &getModuleManager() const { return ModuleMgr; }

/// Retrieve the preprocessor.
Preprocessor &getPreprocessor() const { return PP; }
Expand Down Expand Up @@ -2177,8 +2178,8 @@ class ASTReader

/// Retrieve the global submodule ID given a module and its local ID
/// number.
serialization::SubmoduleID
getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID);
serialization::SubmoduleID getGlobalSubmoduleID(ModuleFile &M,
unsigned LocalID) const;

/// Retrieve the submodule that corresponds to a global submodule ID.
///
Expand All @@ -2191,7 +2192,7 @@ class ASTReader

/// Retrieve the module file with a given local ID within the specified
/// ModuleFile.
ModuleFile *getLocalModuleFile(ModuleFile &M, unsigned ID);
ModuleFile *getLocalModuleFile(ModuleFile &M, unsigned ID) const;

/// Get an ID for the given module file.
unsigned getModuleFileID(ModuleFile *M);
Expand Down Expand Up @@ -2227,33 +2228,46 @@ class ASTReader
return Sema::AlignPackInfo::getFromRawEncoding(Raw);
}

using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;

/// Read a source location from raw form and return it in its
/// originating module file's source location space.
SourceLocation ReadUntranslatedSourceLocation(SourceLocation::UIntTy Raw,
LocSeq *Seq = nullptr) const {
std::pair<SourceLocation, unsigned>
ReadUntranslatedSourceLocation(RawLocEncoding Raw,
LocSeq *Seq = nullptr) const {
return SourceLocationEncoding::decode(Raw, Seq);
}

/// Read a source location from raw form.
SourceLocation ReadSourceLocation(ModuleFile &ModuleFile,
SourceLocation::UIntTy Raw,
SourceLocation ReadSourceLocation(ModuleFile &MF, RawLocEncoding Raw,
LocSeq *Seq = nullptr) const {
SourceLocation Loc = ReadUntranslatedSourceLocation(Raw, Seq);
return TranslateSourceLocation(ModuleFile, Loc);
if (!MF.ModuleOffsetMap.empty())
ReadModuleOffsetMap(MF);

auto [Loc, ModuleFileIndex] = ReadUntranslatedSourceLocation(Raw, Seq);
ModuleFile *OwningModuleFile =
ModuleFileIndex == 0 ? &MF : MF.DependentModules[ModuleFileIndex - 1];

assert(!SourceMgr.isLoadedSourceLocation(Loc) &&
"Run out source location space");

return TranslateSourceLocation(*OwningModuleFile, Loc);
}

/// Translate a source location from another module file's source
/// location space into ours.
SourceLocation TranslateSourceLocation(ModuleFile &ModuleFile,
SourceLocation Loc) const {
if (!ModuleFile.ModuleOffsetMap.empty())
ReadModuleOffsetMap(ModuleFile);
assert(ModuleFile.SLocRemap.find(Loc.getOffset()) !=
ModuleFile.SLocRemap.end() &&
"Cannot find offset to remap.");
SourceLocation::IntTy Remap =
ModuleFile.SLocRemap.find(Loc.getOffset())->second;
return Loc.getLocWithOffset(Remap);
if (Loc.isInvalid())
return Loc;

// FIXME: TranslateSourceLocation is not re-enterable. It is problematic
// to call TranslateSourceLocation on a translated source location.
// We either need a method to know whether or not a source location is
// translated or refactor the code to make it clear that
// TranslateSourceLocation won't be called with translated source location.

return Loc.getLocWithOffset(ModuleFile.SLocEntryBaseOffset - 2);
}

/// Read a source location.
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Serialization/ASTRecordReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@ class ASTRecordReader
/// Read a list of Exprs used for a var-list.
llvm::SmallVector<Expr *> readOpenACCVarList();

/// Read a list of Exprs used for a int-expr-list.
llvm::SmallVector<Expr *> readOpenACCIntExprList();

/// Read an OpenACC clause, advancing Idx.
OpenACCClause *readOpenACCClause();

Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Serialization/ASTRecordWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,8 @@ class ASTRecordWriter

void writeOpenACCVarList(const OpenACCClauseWithVarList *C);

void writeOpenACCIntExprList(ArrayRef<Expr *> Exprs);

/// Writes out a single OpenACC Clause.
void writeOpenACCClause(const OpenACCClause *C);

Expand Down
13 changes: 12 additions & 1 deletion clang/include/clang/Serialization/ASTWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ class ASTWriter : public ASTDeserializationListener,

/// Offset of each type in the bitstream, indexed by
/// the type's ID.
std::vector<serialization::UnderalignedInt64> TypeOffsets;
std::vector<serialization::UnalignedUInt64> TypeOffsets;

/// The first ID number we can use for our own identifiers.
serialization::IdentID FirstIdentID = serialization::NUM_PREDEF_IDENT_IDS;
Expand Down Expand Up @@ -357,6 +357,13 @@ class ASTWriter : public ASTDeserializationListener,
/// contexts.
llvm::DenseMap<const Decl *, unsigned> AnonymousDeclarationNumbers;

/// The external top level module during the writing process. Used to
/// generate signature for the module file being written.
///
/// Only meaningful for standard C++ named modules. See the comments in
/// createSignatureForNamedModule() for details.
llvm::DenseSet<Module *> TouchedTopLevelModules;

/// An update to a Decl.
class DeclUpdate {
/// A DeclUpdateKind.
Expand Down Expand Up @@ -676,6 +683,10 @@ class ASTWriter : public ASTDeserializationListener,
void AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record,
LocSeq *Seq = nullptr);

/// Return the raw encodings for source locations.
SourceLocationEncoding::RawLocEncoding
getRawSourceLocationEncoding(SourceLocation Loc, LocSeq *Seq = nullptr);

/// Emit a source range.
void AddSourceRange(SourceRange Range, RecordDataImpl &Record,
LocSeq *Seq = nullptr);
Expand Down
16 changes: 10 additions & 6 deletions clang/include/clang/Serialization/ModuleFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,10 +295,6 @@ class ModuleFile {
/// AST file.
const uint32_t *SLocEntryOffsets = nullptr;

/// Remapping table for source locations in this module.
ContinuousRangeMap<SourceLocation::UIntTy, SourceLocation::IntTy, 2>
SLocRemap;

// === Identifiers ===

/// The number of identifiers in this AST file.
Expand Down Expand Up @@ -495,7 +491,7 @@ class ModuleFile {

/// Offset of each type within the bitstream, indexed by the
/// type ID, or the representation of a Type*.
const UnderalignedInt64 *TypeOffsets = nullptr;
const UnalignedUInt64 *TypeOffsets = nullptr;

/// Base type ID for types local to this module as represented in
/// the global type ID space.
Expand All @@ -512,9 +508,17 @@ class ModuleFile {
/// List of modules which depend on this module
llvm::SetVector<ModuleFile *> ImportedBy;

/// List of modules which this module depends on
/// List of modules which this module directly imported
llvm::SetVector<ModuleFile *> Imports;

/// List of modules which this modules dependent on. Different
/// from `Imports`, this includes indirectly imported modules too.
/// The order of DependentModules is significant. It should keep
/// the same order with that module file manager when we write
/// the current module file. The value of the member will be initialized
/// in `ASTReader::ReadModuleOffsetMap`.
llvm::SmallVector<ModuleFile *, 16> DependentModules;

/// Determine whether this module was directly imported at
/// any point during translation.
bool isDirectlyImported() const { return DirectlyImported; }
Expand Down
91 changes: 65 additions & 26 deletions clang/include/clang/Serialization/SourceLocationEncoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,33 @@
//
//===----------------------------------------------------------------------===//
//
// Source locations are stored pervasively in the AST, making up a third of
// the size of typical serialized files. Storing them efficiently is important.
// We wish to encode the SourceLocation from other module file not dependent
// on the other module file. So that the source location changes from other
// module file may not affect the contents of the current module file. Then the
// users don't need to recompile the whole project due to a new line in a module
// unit in the root of the dependency graph.
//
// We use integers optimized by VBR-encoding, because:
// - when abbreviations cannot be used, VBR6 encoding is our only choice
// - in the worst case a SourceLocation can be ~any 32-bit number, but in
// practice they are highly predictable
// To achieve this, we need to encode the index of the module file into the
// encoding of the source location. The encoding of the source location may be:
//
// We encode the integer so that likely values encode as small numbers that
// turn into few VBR chunks:
// - the invalid sentinel location is a very common value: it encodes as 0
// - the "macro or not" bit is stored at the bottom of the integer
// (rather than at the top, as in memory), so macro locations can have
// small representations.
// - related locations (e.g. of a left and right paren pair) are usually
// similar, so when encoding a sequence of locations we store only
// differences between successive elements.
// |-----------------------|-----------------------|
// | A | B | C |
//
// * A: 32 bit. The index of the module file in the module manager + 1. The +1
// here is necessary since we wish 0 stands for the current module file.
// * B: 31 bit. The offset of the source location to the module file containing
// it.
// * C: The macro bit. We rotate it to the lowest bit so that we can save some
// space in case the index of the module file is 0.
//
// Specially, if the index of the module file is 0, we allow to encode a
// sequence of locations we store only differences between successive elements.
//
//===----------------------------------------------------------------------===//

#include <climits>
#include "clang/Basic/SourceLocation.h"
#include "llvm/Support/MathExtras.h"
#include <climits>

#ifndef LLVM_CLANG_SERIALIZATION_SOURCELOCATIONENCODING_H
#define LLVM_CLANG_SERIALIZATION_SOURCELOCATIONENCODING_H
Expand All @@ -52,9 +57,13 @@ class SourceLocationEncoding {
friend SourceLocationSequence;

public:
static uint64_t encode(SourceLocation Loc,
SourceLocationSequence * = nullptr);
static SourceLocation decode(uint64_t, SourceLocationSequence * = nullptr);
using RawLocEncoding = uint64_t;

static RawLocEncoding encode(SourceLocation Loc, UIntTy BaseOffset,
unsigned BaseModuleFileIndex,
SourceLocationSequence * = nullptr);
static std::pair<SourceLocation, unsigned>
decode(RawLocEncoding, SourceLocationSequence * = nullptr);
};

/// Serialized encoding of a sequence of SourceLocations.
Expand Down Expand Up @@ -149,14 +158,44 @@ class SourceLocationSequence::State {
operator SourceLocationSequence *() { return &Seq; }
};

inline uint64_t SourceLocationEncoding::encode(SourceLocation Loc,
SourceLocationSequence *Seq) {
return Seq ? Seq->encode(Loc) : encodeRaw(Loc.getRawEncoding());
inline SourceLocationEncoding::RawLocEncoding
SourceLocationEncoding::encode(SourceLocation Loc, UIntTy BaseOffset,
unsigned BaseModuleFileIndex,
SourceLocationSequence *Seq) {
// If the source location is a local source location, we can try to optimize
// the similar sequences to only record the differences.
if (!BaseOffset)
return Seq ? Seq->encode(Loc) : encodeRaw(Loc.getRawEncoding());

if (Loc.isInvalid())
return 0;

// Otherwise, the higher bits are used to store the module file index,
// so it is meaningless to optimize the source locations into small
// integers. Let's try to always use the raw encodings.
assert(Loc.getOffset() >= BaseOffset);
Loc = Loc.getLocWithOffset(-BaseOffset);
RawLocEncoding Encoded = encodeRaw(Loc.getRawEncoding());

// 16 bits should be sufficient to store the module file index.
assert(BaseModuleFileIndex < (1 << 16));
Encoded |= (RawLocEncoding)BaseModuleFileIndex << 32;
return Encoded;
}
inline SourceLocation
SourceLocationEncoding::decode(uint64_t Encoded, SourceLocationSequence *Seq) {
return Seq ? Seq->decode(Encoded)
: SourceLocation::getFromRawEncoding(decodeRaw(Encoded));
inline std::pair<SourceLocation, unsigned>
SourceLocationEncoding::decode(RawLocEncoding Encoded,
SourceLocationSequence *Seq) {
unsigned ModuleFileIndex = Encoded >> 32;

if (!ModuleFileIndex)
return {Seq ? Seq->decode(Encoded)
: SourceLocation::getFromRawEncoding(decodeRaw(Encoded)),
ModuleFileIndex};

Encoded &= llvm::maskTrailingOnes<RawLocEncoding>(32);
SourceLocation Loc = SourceLocation::getFromRawEncoding(decodeRaw(Encoded));

return {Loc, ModuleFileIndex};
}

} // namespace clang
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -1397,7 +1397,7 @@ def CastValueChecker : Checker<"CastValue">,
Documentation<NotDocumented>;

def ReturnValueChecker : Checker<"ReturnValue">,
HelpText<"Model the guaranteed boolean return value of function calls">,
HelpText<"Model certain Error() methods that always return true by convention">,
Documentation<NotDocumented>;

} // end "apiModeling.llvm"
Expand Down
42 changes: 22 additions & 20 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
// Placeholder type for bound members.
InitBuiltinType(BoundMemberTy, BuiltinType::BoundMember);

// Placeholder type for unresolved templates.
InitBuiltinType(UnresolvedTemplateTy, BuiltinType::UnresolvedTemplate);

// Placeholder type for pseudo-objects.
InitBuiltinType(PseudoObjectTy, BuiltinType::PseudoObject);

Expand Down Expand Up @@ -2255,9 +2258,8 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
}
case Type::BitInt: {
const auto *EIT = cast<BitIntType>(T);
Align = std::clamp<unsigned>(llvm::PowerOf2Ceil(EIT->getNumBits()),
getCharWidth(), Target->getLongLongAlign());
Width = llvm::alignTo(EIT->getNumBits(), Align);
Align = Target->getBitIntAlign(EIT->getNumBits());
Width = Target->getBitIntWidth(EIT->getNumBits());
break;
}
case Type::Record:
Expand Down Expand Up @@ -3794,33 +3796,33 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType,
numElements->isValueDependent()) &&
"Size must be type- or value-dependent!");

SplitQualType canonElementType = getCanonicalType(elementType).split();

void *insertPos = nullptr;
llvm::FoldingSetNodeID ID;
DependentSizedArrayType::Profile(
ID, *this, numElements ? QualType(canonElementType.Ty, 0) : elementType,
ASM, elementTypeQuals, numElements);

// Look for an existing type with these properties.
DependentSizedArrayType *canonTy =
DependentSizedArrayTypes.FindNodeOrInsertPos(ID, insertPos);

// Dependently-sized array types that do not have a specified number
// of elements will have their sizes deduced from a dependent
// initializer. We do no canonicalization here at all, which is okay
// because they can't be used in most locations.
// initializer.
if (!numElements) {
if (canonTy)
return QualType(canonTy, 0);

auto *newType = new (*this, alignof(DependentSizedArrayType))
DependentSizedArrayType(elementType, QualType(), numElements, ASM,
elementTypeQuals, brackets);
DependentSizedArrayTypes.InsertNode(newType, insertPos);
Types.push_back(newType);
return QualType(newType, 0);
}

// Otherwise, we actually build a new type every time, but we
// also build a canonical type.

SplitQualType canonElementType = getCanonicalType(elementType).split();

void *insertPos = nullptr;
llvm::FoldingSetNodeID ID;
DependentSizedArrayType::Profile(ID, *this,
QualType(canonElementType.Ty, 0),
ASM, elementTypeQuals, numElements);

// Look for an existing type with these properties.
DependentSizedArrayType *canonTy =
DependentSizedArrayTypes.FindNodeOrInsertPos(ID, insertPos);

// If we don't have one, build one.
if (!canonTy) {
canonTy = new (*this, alignof(DependentSizedArrayType))
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5758,3 +5758,18 @@ ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC,
ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) ExportDecl(nullptr, SourceLocation());
}

bool clang::IsArmStreamingFunction(const FunctionDecl *FD,
bool IncludeLocallyStreaming) {
if (IncludeLocallyStreaming)
if (FD->hasAttr<ArmLocallyStreamingAttr>())
return true;

if (const Type *Ty = FD->getType().getTypePtrOrNull())
if (const auto *FPT = Ty->getAs<FunctionProtoType>())
if (FPT->getAArch64SMEAttributes() &
FunctionType::SME_PStateSMEnabledMask)
return true;

return false;
}
12 changes: 7 additions & 5 deletions clang/lib/AST/Interp/ByteCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,13 @@ Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) {
// InterpStack when calling the function.
bool HasThisPointer = false;
if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) {
if (MD->isImplicitObjectMemberFunction() && !IsLambdaStaticInvoker) {
HasThisPointer = true;
ParamTypes.push_back(PT_Ptr);
ParamOffsets.push_back(ParamOffset);
ParamOffset += align(primSize(PT_Ptr));
if (!IsLambdaStaticInvoker) {
HasThisPointer = MD->isInstance();
if (MD->isImplicitObjectMemberFunction()) {
ParamTypes.push_back(PT_Ptr);
ParamOffsets.push_back(ParamOffset);
ParamOffset += align(primSize(PT_Ptr));
}
}

// Set up lambda capture to closure record field mapping.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2025,7 +2025,7 @@ bool ByteCodeExprGen<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
if (!this->visit(Init))
return false;

if (!this->emitSetField(*T, F.Offset, E))
if (!this->emitInitField(*T, F.Offset, E))
return false;
} else {
if (!this->emitDupPtr(E))
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/AST/Interp/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,8 @@ Pointer::~Pointer() {
}

void Pointer::operator=(const Pointer &P) {

if (!this->isIntegralPointer() || !P.isBlockPointer())
assert(P.StorageKind == StorageKind);
assert(P.StorageKind == StorageKind || (this->isZero() && P.isZero()));

bool WasBlockPointer = isBlockPointer();
StorageKind = P.StorageKind;
Expand All @@ -92,7 +91,7 @@ void Pointer::operator=(const Pointer &P) {

void Pointer::operator=(Pointer &&P) {
if (!this->isIntegralPointer() || !P.isBlockPointer())
assert(P.StorageKind == StorageKind);
assert(P.StorageKind == StorageKind || (this->isZero() && P.isZero()));

bool WasBlockPointer = isBlockPointer();
StorageKind = P.StorageKind;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/NSAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/WebAssemblyReferenceTypes.def"
case BuiltinType::BoundMember:
case BuiltinType::UnresolvedTemplate:
case BuiltinType::Dependent:
case BuiltinType::Overload:
case BuiltinType::UnknownAny:
Expand Down
95 changes: 95 additions & 0 deletions clang/lib/AST/OpenACCClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,38 @@ OpenACCVectorLengthClause::Create(const ASTContext &C, SourceLocation BeginLoc,
OpenACCVectorLengthClause(BeginLoc, LParenLoc, IntExpr, EndLoc);
}

OpenACCAsyncClause::OpenACCAsyncClause(SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *IntExpr,
SourceLocation EndLoc)
: OpenACCClauseWithSingleIntExpr(OpenACCClauseKind::Async, BeginLoc,
LParenLoc, IntExpr, EndLoc) {
assert((!IntExpr || IntExpr->isInstantiationDependent() ||
IntExpr->getType()->isIntegerType()) &&
"Condition expression type not scalar/dependent");
}

OpenACCAsyncClause *OpenACCAsyncClause::Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
Expr *IntExpr,
SourceLocation EndLoc) {
void *Mem =
C.Allocate(sizeof(OpenACCAsyncClause), alignof(OpenACCAsyncClause));
return new (Mem) OpenACCAsyncClause(BeginLoc, LParenLoc, IntExpr, EndLoc);
}

OpenACCWaitClause *OpenACCWaitClause::Create(
const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *DevNumExpr, SourceLocation QueuesLoc, ArrayRef<Expr *> QueueIdExprs,
SourceLocation EndLoc) {
// Allocates enough room in trailing storage for all the int-exprs, plus a
// placeholder for the devnum.
void *Mem = C.Allocate(
OpenACCWaitClause::totalSizeToAlloc<Expr *>(QueueIdExprs.size() + 1));
return new (Mem) OpenACCWaitClause(BeginLoc, LParenLoc, DevNumExpr, QueuesLoc,
QueueIdExprs, EndLoc);
}

OpenACCNumGangsClause *OpenACCNumGangsClause::Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
Expand Down Expand Up @@ -156,6 +188,26 @@ OpenACCFirstPrivateClause *OpenACCFirstPrivateClause::Create(
OpenACCFirstPrivateClause(BeginLoc, LParenLoc, VarList, EndLoc);
}

OpenACCAttachClause *OpenACCAttachClause::Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
ArrayRef<Expr *> VarList,
SourceLocation EndLoc) {
void *Mem =
C.Allocate(OpenACCAttachClause::totalSizeToAlloc<Expr *>(VarList.size()));
return new (Mem) OpenACCAttachClause(BeginLoc, LParenLoc, VarList, EndLoc);
}

OpenACCDevicePtrClause *OpenACCDevicePtrClause::Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
ArrayRef<Expr *> VarList,
SourceLocation EndLoc) {
void *Mem = C.Allocate(
OpenACCDevicePtrClause::totalSizeToAlloc<Expr *>(VarList.size()));
return new (Mem) OpenACCDevicePtrClause(BeginLoc, LParenLoc, VarList, EndLoc);
}

OpenACCNoCreateClause *OpenACCNoCreateClause::Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
Expand Down Expand Up @@ -267,6 +319,15 @@ void OpenACCClausePrinter::VisitVectorLengthClause(
OS << ")";
}

void OpenACCClausePrinter::VisitAsyncClause(const OpenACCAsyncClause &C) {
OS << "async";
if (C.hasIntExpr()) {
OS << "(";
printExpr(C.getIntExpr());
OS << ")";
}
}

void OpenACCClausePrinter::VisitPrivateClause(const OpenACCPrivateClause &C) {
OS << "private(";
llvm::interleaveComma(C.getVarList(), OS,
Expand All @@ -282,6 +343,21 @@ void OpenACCClausePrinter::VisitFirstPrivateClause(
OS << ")";
}

void OpenACCClausePrinter::VisitAttachClause(const OpenACCAttachClause &C) {
OS << "attach(";
llvm::interleaveComma(C.getVarList(), OS,
[&](const Expr *E) { printExpr(E); });
OS << ")";
}

void OpenACCClausePrinter::VisitDevicePtrClause(
const OpenACCDevicePtrClause &C) {
OS << "deviceptr(";
llvm::interleaveComma(C.getVarList(), OS,
[&](const Expr *E) { printExpr(E); });
OS << ")";
}

void OpenACCClausePrinter::VisitNoCreateClause(const OpenACCNoCreateClause &C) {
OS << "no_create(";
llvm::interleaveComma(C.getVarList(), OS,
Expand Down Expand Up @@ -329,3 +405,22 @@ void OpenACCClausePrinter::VisitCreateClause(const OpenACCCreateClause &C) {
[&](const Expr *E) { printExpr(E); });
OS << ")";
}

void OpenACCClausePrinter::VisitWaitClause(const OpenACCWaitClause &C) {
OS << "wait";
if (!C.getLParenLoc().isInvalid()) {
OS << "(";
if (C.hasDevNumExpr()) {
OS << "devnum: ";
printExpr(C.getDevNumExpr());
OS << " : ";
}

if (C.hasQueuesTag())
OS << "queues: ";

llvm::interleaveComma(C.getQueueIdExprs(), OS,
[&](const Expr *E) { printExpr(E); });
OS << ")";
}
}
24 changes: 24 additions & 0 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2543,6 +2543,18 @@ void OpenACCClauseProfiler::VisitFirstPrivateClause(
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitAttachClause(
const OpenACCAttachClause &Clause) {
for (auto *E : Clause.getVarList())
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitDevicePtrClause(
const OpenACCDevicePtrClause &Clause) {
for (auto *E : Clause.getVarList())
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitNoCreateClause(
const OpenACCNoCreateClause &Clause) {
for (auto *E : Clause.getVarList())
Expand All @@ -2561,6 +2573,18 @@ void OpenACCClauseProfiler::VisitVectorLengthClause(
"vector_length clause requires a valid int expr");
Profiler.VisitStmt(Clause.getIntExpr());
}

void OpenACCClauseProfiler::VisitAsyncClause(const OpenACCAsyncClause &Clause) {
if (Clause.hasIntExpr())
Profiler.VisitStmt(Clause.getIntExpr());
}

void OpenACCClauseProfiler::VisitWaitClause(const OpenACCWaitClause &Clause) {
if (Clause.hasDevNumExpr())
Profiler.VisitStmt(Clause.getDevNumExpr());
for (auto *E : Clause.getQueueIdExprs())
Profiler.VisitStmt(E);
}
} // namespace

void StmtProfiler::VisitOpenACCComputeConstruct(
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,10 +397,13 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
case OpenACCClauseKind::Default:
OS << '(' << cast<OpenACCDefaultClause>(C)->getDefaultClauseKind() << ')';
break;
case OpenACCClauseKind::Async:
case OpenACCClauseKind::Attach:
case OpenACCClauseKind::Copy:
case OpenACCClauseKind::PCopy:
case OpenACCClauseKind::PresentOrCopy:
case OpenACCClauseKind::If:
case OpenACCClauseKind::DevicePtr:
case OpenACCClauseKind::FirstPrivate:
case OpenACCClauseKind::NoCreate:
case OpenACCClauseKind::NumGangs:
Expand Down Expand Up @@ -434,6 +437,13 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
if (cast<OpenACCCreateClause>(C)->isZero())
OS << " : zero";
break;
case OpenACCClauseKind::Wait:
OS << " clause";
if (cast<OpenACCWaitClause>(C)->hasDevNumExpr())
OS << " has devnum";
if (cast<OpenACCWaitClause>(C)->hasQueuesTag())
OS << " has queues tag";
break;
default:
// Nothing to do here.
break;
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,8 @@ void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
ID.AddPointer(ET.getAsOpaquePtr());
ID.AddInteger(llvm::to_underlying(SizeMod));
ID.AddInteger(TypeQuals);
E->Profile(ID, Context, true);
if (E)
E->Profile(ID, Context, true);
}

DependentVectorType::DependentVectorType(QualType ElementType,
Expand Down Expand Up @@ -3393,6 +3394,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
return "<overloaded function type>";
case BoundMember:
return "<bound member function type>";
case UnresolvedTemplate:
return "<unresolved template type>";
case PseudoObject:
return "<pseudo-object type>";
case Dependent:
Expand Down Expand Up @@ -4685,6 +4688,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
#include "clang/AST/BuiltinTypes.def"
return false;

case BuiltinType::UnresolvedTemplate:
// Dependent types that could instantiate to a pointer type.
case BuiltinType::Dependent:
case BuiltinType::Overload:
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/TypeLoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::NullPtr:
case BuiltinType::Overload:
case BuiltinType::Dependent:
case BuiltinType::UnresolvedTemplate:
case BuiltinType::BoundMember:
case BuiltinType::UnknownAny:
case BuiltinType::ARCUnbridgedCast:
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ DataflowAnalysisContext::joinFlowConditions(Atom FirstToken,

Solver::Result DataflowAnalysisContext::querySolver(
llvm::SetVector<const Formula *> Constraints) {
return S->solve(Constraints.getArrayRef());
return S.solve(Constraints.getArrayRef());
}

bool DataflowAnalysisContext::flowConditionImplies(Atom Token,
Expand Down Expand Up @@ -338,10 +338,10 @@ static std::unique_ptr<Logger> makeLoggerFromCommandLine() {
return Logger::html(std::move(StreamFactory));
}

DataflowAnalysisContext::DataflowAnalysisContext(std::unique_ptr<Solver> S,
Options Opts)
: S(std::move(S)), A(std::make_unique<Arena>()), Opts(Opts) {
assert(this->S != nullptr);
DataflowAnalysisContext::DataflowAnalysisContext(
Solver &S, std::unique_ptr<Solver> &&OwnedSolver, Options Opts)
: S(S), OwnedSolver(std::move(OwnedSolver)), A(std::make_unique<Arena>()),
Opts(Opts) {
// If the -dataflow-log command-line flag was set, synthesize a logger.
// This is ugly but provides a uniform method for ad-hoc debugging dataflow-
// based tools.
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,17 @@ class ResultObjectVisitor : public RecursiveASTVisitor<ResultObjectVisitor> {
return RecursiveASTVisitor<ResultObjectVisitor>::TraverseDecl(D);
}

// Don't traverse expressions in unevaluated contexts, as we don't model
// fields that are only used in these.
// Note: The operand of the `noexcept` operator is an unevaluated operand, but
// nevertheless it appears in the Clang CFG, so we don't exclude it here.
bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) { return true; }
bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) { return true; }
bool TraverseCXXTypeidExpr(CXXTypeidExpr *) { return true; }
bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *) {
return true;
}

bool TraverseBindingDecl(BindingDecl *BD) {
// `RecursiveASTVisitor` doesn't traverse holding variables for
// `BindingDecl`s by itself, so we need to tell it to.
Expand Down
29 changes: 23 additions & 6 deletions clang/lib/Analysis/FlowSensitive/Transfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ static BoolValue &evaluateBooleanEquality(const Expr &LHS, const Expr &RHS,
if (auto *RHSBool = dyn_cast_or_null<BoolValue>(RHSValue))
return Env.makeIff(*LHSBool, *RHSBool);

if (auto *LHSPtr = dyn_cast_or_null<PointerValue>(LHSValue))
if (auto *RHSPtr = dyn_cast_or_null<PointerValue>(RHSValue))
// If the storage locations are the same, the pointers definitely compare
// the same. If the storage locations are different, they may still alias,
// so we fall through to the case below that returns an atom.
if (&LHSPtr->getPointeeLoc() == &RHSPtr->getPointeeLoc())
return Env.getBoolLiteralValue(true);

return Env.makeAtomicBoolValue();
}

Expand Down Expand Up @@ -556,14 +564,23 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {

copyRecord(*LocSrc, *LocDst, Env);

// If the expr is a glvalue, we can reasonably assume the operator is
// returning T& and thus we can assign it `LocDst`.
if (S->isGLValue()) {
// The assignment operator can have an arbitrary return type. We model the
// return value only if the return type is the same as or a base class of
// the destination type.
if (S->getType().getCanonicalType().getUnqualifiedType() !=
LocDst->getType().getCanonicalType().getUnqualifiedType()) {
auto ReturnDecl = S->getType()->getAsCXXRecordDecl();
auto DstDecl = LocDst->getType()->getAsCXXRecordDecl();
if (ReturnDecl == nullptr || DstDecl == nullptr)
return;
if (!DstDecl->isDerivedFrom(ReturnDecl))
return;
}

if (S->isGLValue())
Env.setStorageLocation(*S, *LocDst);
} else if (S->getType()->isRecordType()) {
// Assume that the assignment returns the assigned value.
else
copyRecord(*LocDst, Env.getResultObjectLocation(*S), Env);
}

return;
}
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Basic/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct CudaVersionMapEntry {
};
#define CUDA_ENTRY(major, minor) \
{ \
#major "." #minor, CudaVersion::CUDA_##major##minor, \
#major "." #minor, CudaVersion::CUDA_##major##minor, \
llvm::VersionTuple(major, minor) \
}

Expand All @@ -41,6 +41,7 @@ static const CudaVersionMapEntry CudaNameVersionMap[] = {
CUDA_ENTRY(12, 1),
CUDA_ENTRY(12, 2),
CUDA_ENTRY(12, 3),
CUDA_ENTRY(12, 4),
{"", CudaVersion::NEW, llvm::VersionTuple(std::numeric_limits<int>::max())},
{"unknown", CudaVersion::UNKNOWN, {}} // End of list tombstone.
};
Expand Down Expand Up @@ -241,7 +242,7 @@ CudaVersion MaxVersionForCudaArch(CudaArch A) {
}
}

bool CudaFeatureEnabled(llvm::VersionTuple Version, CudaFeature Feature) {
bool CudaFeatureEnabled(llvm::VersionTuple Version, CudaFeature Feature) {
return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
}

Expand Down
10 changes: 5 additions & 5 deletions clang/lib/Basic/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ bool Module::isUnimportable(const LangOptions &LangOpts,
return true;
}
for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) {
if (hasFeature(Current->Requirements[I].first, LangOpts, Target) !=
Current->Requirements[I].second) {
if (hasFeature(Current->Requirements[I].FeatureName, LangOpts, Target) !=
Current->Requirements[I].RequiredState) {
Req = Current->Requirements[I];
return true;
}
Expand Down Expand Up @@ -319,7 +319,7 @@ bool Module::directlyUses(const Module *Requested) {
void Module::addRequirement(StringRef Feature, bool RequiredState,
const LangOptions &LangOpts,
const TargetInfo &Target) {
Requirements.push_back(Requirement(std::string(Feature), RequiredState));
Requirements.push_back(Requirement{std::string(Feature), RequiredState});

// If this feature is currently available, we're done.
if (hasFeature(Feature, LangOpts, Target) == RequiredState)
Expand Down Expand Up @@ -504,9 +504,9 @@ void Module::print(raw_ostream &OS, unsigned Indent, bool Dump) const {
for (unsigned I = 0, N = Requirements.size(); I != N; ++I) {
if (I)
OS << ", ";
if (!Requirements[I].second)
if (!Requirements[I].RequiredState)
OS << "!";
OS << Requirements[I].first;
OS << Requirements[I].FeatureName;
}
OS << "\n";
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ using namespace clang::targets;
TargetInfo *
TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
const std::shared_ptr<TargetOptions> &Opts) {
llvm::Triple Triple(Opts->Triple);
llvm::Triple Triple(llvm::Triple::normalize(Opts->Triple));

// Construct the target
std::unique_ptr<TargetInfo> Target = AllocateTarget(Triple, *Opts);
Expand Down
15 changes: 8 additions & 7 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
else
LongWidth = LongAlign = PointerWidth = PointerAlign = 32;

BitIntMaxAlign = 128;
MaxVectorAlign = 128;
MaxAtomicInlineWidth = 128;
MaxAtomicPromoteWidth = 128;
Expand Down Expand Up @@ -224,7 +225,7 @@ bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
BranchProtectionInfo &BPI,
StringRef &Err) const {
llvm::ARM::ParsedBranchProtection PBP;
if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err))
if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err, HasPAuthLR))
return false;

BPI.SignReturnAddr =
Expand Down Expand Up @@ -1480,11 +1481,11 @@ AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
void AArch64leTargetInfo::setDataLayout() {
if (getTriple().isOSBinFormatMachO()) {
if(getTriple().isArch32Bit())
resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128", "_");
resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128-Fn32", "_");
else
resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128", "_");
resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128-Fn32", "_");
} else
resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32");
}

void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
Expand All @@ -1507,7 +1508,7 @@ void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,

void AArch64beTargetInfo::setDataLayout() {
assert(!getTriple().isOSBinFormatMachO());
resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32");
}

WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
Expand All @@ -1530,8 +1531,8 @@ WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,

void WindowsARM64TargetInfo::setDataLayout() {
resetDataLayout(Triple.isOSBinFormatMachO()
? "e-m:o-i64:64-i128:128-n32:64-S128"
: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128",
? "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"
: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32",
Triple.isOSBinFormatMachO() ? "_" : "");
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple,

HasLegalHalfType = true;
HasFloat16 = true;
WavefrontSize = GPUFeatures & llvm::AMDGPU::FEATURE_WAVE32 ? 32 : 64;
WavefrontSize = (GPUFeatures & llvm::AMDGPU::FEATURE_WAVE32) ? 32 : 64;
AllowAMDGPUUnsafeFPAtomics = Opts.AllowAMDGPUUnsafeFPAtomics;

// Set pointer width and alignment for the generic address space.
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Basic/Targets/PPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
IsISA3_1 = true;
} else if (Feature == "+quadword-atomics") {
HasQuadwordAtomics = true;
} else if (Feature == "+aix-shared-lib-tls-model-opt") {
HasAIXShLibTLSModelOpt = true;
}
// TODO: Finish this list and add an assert that we've handled them
// all.
Expand Down Expand Up @@ -580,6 +582,9 @@ bool PPCTargetInfo::initFeatureMap(
Features["aix-small-local-exec-tls"] = false;
Features["aix-small-local-dynamic-tls"] = false;

// Turn off TLS model opt by default.
Features["aix-shared-lib-tls-model-opt"] = false;

Features["spe"] = llvm::StringSwitch<bool>(CPU)
.Case("8548", true)
.Case("e500", true)
Expand Down Expand Up @@ -722,6 +727,7 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const {
.Case("isa-v30-instructions", IsISA3_0)
.Case("isa-v31-instructions", IsISA3_1)
.Case("quadword-atomics", HasQuadwordAtomics)
.Case("aix-shared-lib-tls-model-opt", HasAIXShLibTLSModelOpt)
.Default(false);
}

Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/PPC.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
bool IsISA3_0 = false;
bool IsISA3_1 = false;
bool HasQuadwordAtomics = false;
bool HasAIXShLibTLSModelOpt = false;

protected:
std::string ABI;
Expand Down
19 changes: 18 additions & 1 deletion clang/lib/Basic/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ static const char *const GCCRegNames[] = {
"dr0", "dr1", "dr2", "dr3", "dr6", "dr7",
"bnd0", "bnd1", "bnd2", "bnd3",
"tmm0", "tmm1", "tmm2", "tmm3", "tmm4", "tmm5", "tmm6", "tmm7",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
};

const TargetInfo::AddlRegName AddlRegNames[] = {
Expand All @@ -83,8 +85,23 @@ const TargetInfo::AddlRegName AddlRegNames[] = {
{{"r13d", "r13w", "r13b"}, 43},
{{"r14d", "r14w", "r14b"}, 44},
{{"r15d", "r15w", "r15b"}, 45},
{{"r16d", "r16w", "r16b"}, 165},
{{"r17d", "r17w", "r17b"}, 166},
{{"r18d", "r18w", "r18b"}, 167},
{{"r19d", "r19w", "r19b"}, 168},
{{"r20d", "r20w", "r20b"}, 169},
{{"r21d", "r21w", "r21b"}, 170},
{{"r22d", "r22w", "r22b"}, 171},
{{"r23d", "r23w", "r23b"}, 172},
{{"r24d", "r24w", "r24b"}, 173},
{{"r25d", "r25w", "r25b"}, 174},
{{"r26d", "r26w", "r26b"}, 175},
{{"r27d", "r27w", "r27b"}, 176},
{{"r28d", "r28w", "r28b"}, 177},
{{"r29d", "r29w", "r29b"}, 178},
{{"r30d", "r30w", "r30b"}, 179},
{{"r31d", "r31w", "r31b"}, 180},
};

} // namespace targets
} // namespace clang

Expand Down
11 changes: 3 additions & 8 deletions clang/lib/CodeGen/BackendConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class BackendConsumer : public ASTConsumer {
const CodeGenOptions &CodeGenOpts;
const TargetOptions &TargetOpts;
const LangOptions &LangOpts;
const FileManager &FileMgr;
std::unique_ptr<raw_pwrite_stream> AsmOutStream;
ASTContext *Context;
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
Expand Down Expand Up @@ -76,7 +75,7 @@ class BackendConsumer : public ASTConsumer {
const PreprocessorOptions &PPOpts,
const CodeGenOptions &CodeGenOpts,
const TargetOptions &TargetOpts, const LangOptions &LangOpts,
const FileManager &FileMgr, const std::string &InFile,
const std::string &InFile,
SmallVector<LinkModule, 4> LinkModules,
std::unique_ptr<raw_pwrite_stream> OS, llvm::LLVMContext &C,
CoverageSourceInfo *CoverageInfo = nullptr);
Expand All @@ -90,8 +89,8 @@ class BackendConsumer : public ASTConsumer {
const PreprocessorOptions &PPOpts,
const CodeGenOptions &CodeGenOpts,
const TargetOptions &TargetOpts, const LangOptions &LangOpts,
const FileManager &FileMgr, llvm::Module *Module,
SmallVector<LinkModule, 4> LinkModules, llvm::LLVMContext &C,
llvm::Module *Module, SmallVector<LinkModule, 4> LinkModules,
llvm::LLVMContext &C,
CoverageSourceInfo *CoverageInfo = nullptr);

llvm::Module *getModule() const;
Expand All @@ -115,10 +114,6 @@ class BackendConsumer : public ASTConsumer {
// Links each entry in LinkModules into our module. Returns true on error.
bool LinkInModules(llvm::Module *M, bool ShouldLinkFiles = true);

// Load a bitcode module from -mlink-builtin-bitcode option using
// methods from a BackendConsumer instead of CompilerInstance
bool ReloadModules(llvm::Module *M);

/// Get the best possible source location to represent a diagnostic that
/// may have associated debug info.
const FullSourceLoc getBestLocationFromDebugLoc(
Expand Down
13 changes: 3 additions & 10 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,6 @@ static cl::opt<PGOOptions::ColdFuncOpt> ClPGOColdFuncAttr(
"Mark cold functions with optnone.")));

extern cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate;

// Re-link builtin bitcodes after optimization
cl::opt<bool> ClRelinkBuiltinBitcodePostop(
"relink-builtin-bitcode-postop", cl::Optional,
cl::desc("Re-link builtin bitcodes after optimization."));
} // namespace llvm

namespace {
Expand Down Expand Up @@ -423,6 +418,7 @@ static bool initTargetOptions(DiagnosticsEngine &Diags,
Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames;
Options.UniqueBasicBlockSectionNames =
CodeGenOpts.UniqueBasicBlockSectionNames;
Options.SeparateNamedSections = CodeGenOpts.SeparateNamedSections;
Options.TLSSize = CodeGenOpts.TLSSize;
Options.EnableTLSDESC = CodeGenOpts.EnableTLSDESC;
Options.EmulatedTLS = CodeGenOpts.EmulatedTLS;
Expand Down Expand Up @@ -1054,11 +1050,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
}
}

// Re-link against any bitcodes supplied via the -mlink-builtin-bitcode option
// Some optimizations may generate new function calls that would not have
// been linked pre-optimization (i.e. fused sincos calls generated by
// AMDGPULibCalls::fold_sincos.)
if (ClRelinkBuiltinBitcodePostop)
// Link against bitcodes supplied via the -mlink-builtin-bitcode option
if (CodeGenOpts.LinkBitcodePostopt)
MPM.addPass(LinkInModulesPass(BC, false));

// Add a verifier pass if requested. We don't have to do this if the action
Expand Down
24 changes: 19 additions & 5 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,8 +513,8 @@ static Value *emitBinaryMaybeConstrainedFPBuiltin(CodeGenFunction &CGF,
llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0));
llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1));

CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
if (CGF.Builder.getIsFPConstrained()) {
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
Function *F = CGF.CGM.getIntrinsic(ConstrainedIntrinsicID, Src0->getType());
return CGF.Builder.CreateConstrainedFPCall(F, { Src0, Src1 });
} else {
Expand All @@ -530,8 +530,8 @@ static Value *emitBinaryExpMaybeConstrainedFPBuiltin(
llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0));
llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1));

CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
if (CGF.Builder.getIsFPConstrained()) {
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
Function *F = CGF.CGM.getIntrinsic(ConstrainedIntrinsicID,
{Src0->getType(), Src1->getType()});
return CGF.Builder.CreateConstrainedFPCall(F, {Src0, Src1});
Expand All @@ -551,8 +551,8 @@ static Value *emitTernaryMaybeConstrainedFPBuiltin(CodeGenFunction &CGF,
llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1));
llvm::Value *Src2 = CGF.EmitScalarExpr(E->getArg(2));

CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
if (CGF.Builder.getIsFPConstrained()) {
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
Function *F = CGF.CGM.getIntrinsic(ConstrainedIntrinsicID, Src0->getType());
return CGF.Builder.CreateConstrainedFPCall(F, { Src0, Src1, Src2 });
} else {
Expand Down Expand Up @@ -704,6 +704,7 @@ static Value *EmitSignBit(CodeGenFunction &CGF, Value *V) {

static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *FD,
const CallExpr *E, llvm::Constant *calleeValue) {
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
CGCallee callee = CGCallee::forDirect(calleeValue, GlobalDecl(FD));
return CGF.EmitCall(E->getCallee()->getType(), callee, E, ReturnValueSlot());
}
Expand Down Expand Up @@ -2660,7 +2661,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
if (OP.hasMathErrnoOverride())
ErrnoOverriden = OP.getMathErrnoOverride();
}
// True if 'atttibute__((optnone)) is used. This attibute overrides
// True if 'attribute__((optnone))' is used. This attribute overrides
// fast-math which implies math-errno.
bool OptNone = CurFuncDecl && CurFuncDecl->hasAttr<OptimizeNoneAttr>();

Expand Down Expand Up @@ -3821,7 +3822,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_elementwise_sin:
return RValue::get(
emitUnaryBuiltin(*this, E, llvm::Intrinsic::sin, "elt.sin"));

case Builtin::BI__builtin_elementwise_tan:
return RValue::get(
emitUnaryBuiltin(*this, E, llvm::Intrinsic::tan, "elt.tan"));
case Builtin::BI__builtin_elementwise_trunc:
return RValue::get(
emitUnaryBuiltin(*this, E, llvm::Intrinsic::trunc, "elt.trunc"));
Expand Down Expand Up @@ -21302,6 +21305,17 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
CGM.getIntrinsic(Intrinsic::wasm_relaxed_dot_bf16x8_add_f32);
return Builder.CreateCall(Callee, {LHS, RHS, Acc});
}
case WebAssembly::BI__builtin_wasm_loadf16_f32: {
Value *Addr = EmitScalarExpr(E->getArg(0));
Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_loadf16_f32);
return Builder.CreateCall(Callee, {Addr});
}
case WebAssembly::BI__builtin_wasm_storef16_f32: {
Value *Val = EmitScalarExpr(E->getArg(0));
Value *Addr = EmitScalarExpr(E->getArg(1));
Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_storef16_f32);
return Builder.CreateCall(Callee, {Val, Addr});
}
case WebAssembly::BI__builtin_wasm_table_get: {
assert(E->getArg(0)->getType()->isArrayType());
Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this);
Expand Down
11 changes: 6 additions & 5 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5050,13 +5050,14 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
(TargetDecl->hasAttr<TargetAttr>() ||
(CurFuncDecl && CurFuncDecl->hasAttr<TargetAttr>())))
checkTargetFeatures(Loc, FD);

// Some architectures (such as x86-64) have the ABI changed based on
// attribute-target/features. Give them a chance to diagnose.
CGM.getTargetCodeGenInfo().checkFunctionCallABI(
CGM, Loc, dyn_cast_or_null<FunctionDecl>(CurCodeDecl), FD, CallArgs);
}

// Some architectures (such as x86-64) have the ABI changed based on
// attribute-target/features. Give them a chance to diagnose.
CGM.getTargetCodeGenInfo().checkFunctionCallABI(
CGM, Loc, dyn_cast_or_null<FunctionDecl>(CurCodeDecl),
dyn_cast_or_null<FunctionDecl>(TargetDecl), CallArgs, RetTy);

// 1. Set up the arguments.

// If we're using inalloca, insert the allocation after the stack save.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1736,7 +1736,7 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
for (const auto *Field : record->fields())
assert(
(Field->isUnnamedBitField() || Field->isAnonymousStructOrUnion()) &&
"Only unnamed bitfields or ananymous class allowed");
"Only unnamed bitfields or anonymous class allowed");
#endif
return;
}
Expand Down
56 changes: 10 additions & 46 deletions clang/lib/CodeGen/CodeGenAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,6 @@ using namespace llvm;

#define DEBUG_TYPE "codegenaction"

namespace llvm {
extern cl::opt<bool> ClRelinkBuiltinBitcodePostop;
}

namespace clang {
class BackendConsumer;
class ClangDiagnosticHandler final : public DiagnosticHandler {
Expand Down Expand Up @@ -118,13 +114,12 @@ BackendConsumer::BackendConsumer(
const HeaderSearchOptions &HeaderSearchOpts,
const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts,
const TargetOptions &TargetOpts, const LangOptions &LangOpts,
const FileManager &FileMgr, const std::string &InFile,
SmallVector<LinkModule, 4> LinkModules,
const std::string &InFile, SmallVector<LinkModule, 4> LinkModules,
std::unique_ptr<raw_pwrite_stream> OS, LLVMContext &C,
CoverageSourceInfo *CoverageInfo)
: Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts),
CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts),
FileMgr(FileMgr), AsmOutStream(std::move(OS)), Context(nullptr), FS(VFS),
AsmOutStream(std::move(OS)), Context(nullptr), FS(VFS),
LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
LLVMIRGenerationRefCount(0),
Gen(CreateLLVMCodeGen(Diags, InFile, std::move(VFS), HeaderSearchOpts,
Expand All @@ -144,12 +139,11 @@ BackendConsumer::BackendConsumer(
const HeaderSearchOptions &HeaderSearchOpts,
const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts,
const TargetOptions &TargetOpts, const LangOptions &LangOpts,
const FileManager &FileMgr, llvm::Module *Module,
SmallVector<LinkModule, 4> LinkModules, LLVMContext &C,
CoverageSourceInfo *CoverageInfo)
llvm::Module *Module, SmallVector<LinkModule, 4> LinkModules,
LLVMContext &C, CoverageSourceInfo *CoverageInfo)
: Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts),
CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts),
FileMgr(FileMgr), Context(nullptr), FS(VFS),
Context(nullptr), FS(VFS),
LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
LLVMIRGenerationRefCount(0),
Gen(CreateLLVMCodeGen(Diags, "", std::move(VFS), HeaderSearchOpts, PPOpts,
Expand Down Expand Up @@ -232,35 +226,6 @@ void BackendConsumer::HandleInterestingDecl(DeclGroupRef D) {
HandleTopLevelDecl(D);
}

bool BackendConsumer::ReloadModules(llvm::Module *M) {
for (const CodeGenOptions::BitcodeFileToLink &F :
CodeGenOpts.LinkBitcodeFiles) {
auto BCBuf = FileMgr.getBufferForFile(F.Filename);
if (!BCBuf) {
Diags.Report(diag::err_cannot_open_file)
<< F.Filename << BCBuf.getError().message();
LinkModules.clear();
return true;
}

LLVMContext &Ctx = getModule()->getContext();
Expected<std::unique_ptr<llvm::Module>> ModuleOrErr =
getOwningLazyBitcodeModule(std::move(*BCBuf), Ctx);

if (!ModuleOrErr) {
handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
Diags.Report(diag::err_cannot_open_file) << F.Filename << EIB.message();
});
LinkModules.clear();
return true;
}
LinkModules.push_back({std::move(ModuleOrErr.get()), F.PropagateAttrs,
F.Internalize, F.LinkFlags});
}

return false; // success
}

// Links each entry in LinkModules into our module. Returns true on error.
bool BackendConsumer::LinkInModules(llvm::Module *M, bool ShouldLinkFiles) {
for (auto &LM : LinkModules) {
Expand Down Expand Up @@ -362,7 +327,7 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) {
}

// Link each LinkModule into our module.
if (LinkInModules(getModule()))
if (!CodeGenOpts.LinkBitcodePostopt && LinkInModules(getModule()))
return;

for (auto &F : getModule()->functions()) {
Expand Down Expand Up @@ -1055,9 +1020,8 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::unique_ptr<BackendConsumer> Result(new BackendConsumer(
BA, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(),
CI.getTargetOpts(), CI.getLangOpts(), CI.getFileManager(),
std::string(InFile), std::move(LinkModules), std::move(OS), *VMContext,
CoverageInfo));
CI.getTargetOpts(), CI.getLangOpts(), std::string(InFile),
std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo));
BEConsumer = Result.get();

// Enable generating macro debug info only when debug info is not disabled and
Expand Down Expand Up @@ -1228,11 +1192,11 @@ void CodeGenAction::ExecuteAction() {
BackendConsumer Result(BA, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(),
CI.getCodeGenOpts(), CI.getTargetOpts(),
CI.getLangOpts(), CI.getFileManager(), TheModule.get(),
CI.getLangOpts(), TheModule.get(),
std::move(LinkModules), *VMContext, nullptr);

// Link in each pending link module.
if (Result.LinkInModules(&*TheModule))
if (!CodeGenOpts.LinkBitcodePostopt && Result.LinkInModules(&*TheModule))
return;

// PR44896: Force DiscardValueNames as false. DiscardValueNames cannot be
Expand Down
32 changes: 32 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
#include "llvm/IR/AttributeMask.h"
#include "llvm/IR/CallingConv.h"
Expand Down Expand Up @@ -1190,6 +1191,37 @@ void CodeGenModule::Release() {
if (!LangOpts.isSignReturnAddressWithAKey())
getModule().addModuleFlag(llvm::Module::Min,
"sign-return-address-with-bkey", 1);

if (getTriple().isOSLinux()) {
assert(getTriple().isOSBinFormatELF());
using namespace llvm::ELF;
uint64_t PAuthABIVersion =
(LangOpts.PointerAuthIntrinsics
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INTRINSICS) |
(LangOpts.PointerAuthCalls
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_CALLS) |
(LangOpts.PointerAuthReturns
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_RETURNS) |
(LangOpts.PointerAuthAuthTraps
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_AUTHTRAPS) |
(LangOpts.PointerAuthVTPtrAddressDiscrimination
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRADDRDISCR) |
(LangOpts.PointerAuthVTPtrTypeDiscrimination
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRTYPEDISCR) |
(LangOpts.PointerAuthInitFini
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI);
static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI ==
AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST,
"Update when new enum items are defined");
if (PAuthABIVersion != 0) {
getModule().addModuleFlag(llvm::Module::Error,
"aarch64-elf-pauthabi-platform",
AARCH64_PAUTH_PLATFORM_LLVM_LINUX);
getModule().addModuleFlag(llvm::Module::Error,
"aarch64-elf-pauthabi-version",
PAuthABIVersion);
}
}
}

if (CodeGenOpts.StackClashProtector)
Expand Down
5 changes: 1 addition & 4 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,7 @@ class SourceMappingRegion {
bool isBranch() const { return FalseCount.has_value(); }

bool isMCDCDecision() const {
const auto *DecisionParams =
std::get_if<mcdc::DecisionParameters>(&MCDCParams);
assert(!DecisionParams || DecisionParams->NumConditions > 0);
return DecisionParams;
return std::holds_alternative<mcdc::DecisionParameters>(MCDCParams);
}

const auto &getMCDCDecisionParams() const {
Expand Down
8 changes: 2 additions & 6 deletions clang/lib/CodeGen/LinkInModulesPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,8 @@ PreservedAnalyses LinkInModulesPass::run(Module &M, ModuleAnalysisManager &AM) {
if (!BC)
return PreservedAnalyses::all();

// Re-load bitcode modules from files
if (BC->ReloadModules(&M))
report_fatal_error("Bitcode module re-loading failed, aborted!");

if (BC->LinkInModules(&M, ShouldLinkFiles))
report_fatal_error("Bitcode module re-linking failed, aborted!");
report_fatal_error("Bitcode module postopt linking failed, aborted!");

return PreservedAnalyses::all();
return PreservedAnalyses::none();
}
22 changes: 21 additions & 1 deletion clang/lib/CodeGen/MicrosoftCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1122,7 +1122,22 @@ static bool isTrivialForMSVC(const CXXRecordDecl *RD, QualType Ty,
// No base classes
// No virtual functions
// Additionally, we need to ensure that there is a trivial copy assignment
// operator, a trivial destructor and no user-provided constructors.
// operator, a trivial destructor, no user-provided constructors and no
// deleted copy assignment operator.

// We need to cover two cases when checking for a deleted copy assignment
// operator.
//
// struct S { int& r; };
// The above will have an implicit copy assignment operator that is deleted
// and there will not be a `CXXMethodDecl` for the copy assignment operator.
// This is handled by the `needsImplicitCopyAssignment()` check below.
//
// struct S { S& operator=(const S&) = delete; int i; };
// The above will not have an implicit copy assignment operator that is
// deleted but there is a deleted `CXXMethodDecl` for the declared copy
// assignment operator. This is handled by the `isDeleted()` check below.

if (RD->hasProtectedFields() || RD->hasPrivateFields())
return false;
if (RD->getNumBases() > 0)
Expand All @@ -1131,13 +1146,18 @@ static bool isTrivialForMSVC(const CXXRecordDecl *RD, QualType Ty,
return false;
if (RD->hasNonTrivialCopyAssignment())
return false;
if (RD->needsImplicitCopyAssignment() && !RD->hasSimpleCopyAssignment())
return false;
for (const Decl *D : RD->decls()) {
if (auto *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
if (Ctor->isUserProvided())
return false;
} else if (auto *Template = dyn_cast<FunctionTemplateDecl>(D)) {
if (isa<CXXConstructorDecl>(Template->getTemplatedDecl()))
return false;
} else if (auto *MethodDecl = dyn_cast<CXXMethodDecl>(D)) {
if (MethodDecl->isCopyAssignmentOperator() && MethodDecl->isDeleted())
return false;
}
}
if (RD->hasNonTrivialDestructor())
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ class TargetCodeGenInfo {
virtual void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc,
const FunctionDecl *Caller,
const FunctionDecl *Callee,
const CallArgList &Args) const {}
const CallArgList &Args,
QualType ReturnType) const {}

/// Determines the size of struct _Unwind_Exception on this platform,
/// in 8-bit units. The Itanium ABI defines this as:
Expand Down
107 changes: 76 additions & 31 deletions clang/lib/CodeGen/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "ABIInfoImpl.h"
#include "TargetInfo.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "llvm/TargetParser/AArch64TargetParser.h"

Expand Down Expand Up @@ -170,8 +171,22 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {

void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc,
const FunctionDecl *Caller,
const FunctionDecl *Callee,
const CallArgList &Args) const override;
const FunctionDecl *Callee, const CallArgList &Args,
QualType ReturnType) const override;

private:
// Diagnose calls between functions with incompatible Streaming SVE
// attributes.
void checkFunctionCallABIStreaming(CodeGenModule &CGM, SourceLocation CallLoc,
const FunctionDecl *Caller,
const FunctionDecl *Callee) const;
// Diagnose calls which must pass arguments in floating-point registers when
// the selected target does not have floating-point registers.
void checkFunctionCallABISoftFloat(CodeGenModule &CGM, SourceLocation CallLoc,
const FunctionDecl *Caller,
const FunctionDecl *Callee,
const CallArgList &Args,
QualType ReturnType) const;
};

class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo {
Expand Down Expand Up @@ -838,57 +853,56 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
/*allowHigherAlign*/ false);
}

static bool isStreaming(const FunctionDecl *F) {
if (F->hasAttr<ArmLocallyStreamingAttr>())
return true;
if (const auto *T = F->getType()->getAs<FunctionProtoType>())
return T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask;
return false;
}

static bool isStreamingCompatible(const FunctionDecl *F) {
if (const auto *T = F->getType()->getAs<FunctionProtoType>())
return T->getAArch64SMEAttributes() &
FunctionType::SME_PStateSMCompatibleMask;
return false;
}

// Report an error if an argument or return value of type Ty would need to be
// passed in a floating-point register.
static void diagnoseIfNeedsFPReg(DiagnosticsEngine &Diags,
const StringRef ABIName,
const AArch64ABIInfo &ABIInfo,
const QualType &Ty, const NamedDecl *D) {
const Type *HABase = nullptr;
uint64_t HAMembers = 0;
if (Ty->isFloatingType() || Ty->isVectorType() ||
ABIInfo.isHomogeneousAggregate(Ty, HABase, HAMembers)) {
Diags.Report(D->getLocation(), diag::err_target_unsupported_type_for_abi)
<< D->getDeclName() << Ty << ABIName;
}
}

// If we are using a hard-float ABI, but do not have floating point registers,
// then report an error for any function arguments or returns which would be
// passed in floating-pint registers.
void AArch64TargetCodeGenInfo::checkFunctionABI(
CodeGenModule &CGM, const FunctionDecl *FuncDecl) const {
const AArch64ABIInfo &ABIInfo = getABIInfo<AArch64ABIInfo>();
const TargetInfo &TI = ABIInfo.getContext().getTargetInfo();

// If we are using a hard-float ABI, but do not have floating point
// registers, then report an error for any function arguments or returns
// which would be passed in floating-pint registers.
auto CheckType = [&CGM, &TI, &ABIInfo](const QualType &Ty,
const NamedDecl *D) {
const Type *HABase = nullptr;
uint64_t HAMembers = 0;
if (Ty->isFloatingType() || Ty->isVectorType() ||
ABIInfo.isHomogeneousAggregate(Ty, HABase, HAMembers)) {
CGM.getDiags().Report(D->getLocation(),
diag::err_target_unsupported_type_for_abi)
<< D->getDeclName() << Ty << TI.getABI();
}
};

if (!TI.hasFeature("fp") && !ABIInfo.isSoftFloat()) {
CheckType(FuncDecl->getReturnType(), FuncDecl);
diagnoseIfNeedsFPReg(CGM.getDiags(), TI.getABI(), ABIInfo,
FuncDecl->getReturnType(), FuncDecl);
for (ParmVarDecl *PVD : FuncDecl->parameters()) {
CheckType(PVD->getType(), PVD);
diagnoseIfNeedsFPReg(CGM.getDiags(), TI.getABI(), ABIInfo, PVD->getType(),
PVD);
}
}
}

void AArch64TargetCodeGenInfo::checkFunctionCallABI(
void AArch64TargetCodeGenInfo::checkFunctionCallABIStreaming(
CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller,
const FunctionDecl *Callee, const CallArgList &Args) const {
const FunctionDecl *Callee) const {
if (!Caller || !Callee || !Callee->hasAttr<AlwaysInlineAttr>())
return;

bool CallerIsStreaming = isStreaming(Caller);
bool CalleeIsStreaming = isStreaming(Callee);
bool CallerIsStreaming =
IsArmStreamingFunction(Caller, /*IncludeLocallyStreaming=*/true);
bool CalleeIsStreaming =
IsArmStreamingFunction(Callee, /*IncludeLocallyStreaming=*/true);
bool CallerIsStreamingCompatible = isStreamingCompatible(Caller);
bool CalleeIsStreamingCompatible = isStreamingCompatible(Callee);

Expand All @@ -903,6 +917,37 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(
<< Callee->getDeclName();
}

// If the target does not have floating-point registers, but we are using a
// hard-float ABI, there is no way to pass floating-point, vector or HFA values
// to functions, so we report an error.
void AArch64TargetCodeGenInfo::checkFunctionCallABISoftFloat(
CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller,
const FunctionDecl *Callee, const CallArgList &Args,
QualType ReturnType) const {
const AArch64ABIInfo &ABIInfo = getABIInfo<AArch64ABIInfo>();
const TargetInfo &TI = ABIInfo.getContext().getTargetInfo();

if (!Caller || TI.hasFeature("fp") || ABIInfo.isSoftFloat())
return;

diagnoseIfNeedsFPReg(CGM.getDiags(), TI.getABI(), ABIInfo, ReturnType,
Caller);

for (const CallArg &Arg : Args)
diagnoseIfNeedsFPReg(CGM.getDiags(), TI.getABI(), ABIInfo, Arg.getType(),
Caller);
}

void AArch64TargetCodeGenInfo::checkFunctionCallABI(CodeGenModule &CGM,
SourceLocation CallLoc,
const FunctionDecl *Caller,
const FunctionDecl *Callee,
const CallArgList &Args,
QualType ReturnType) const {
checkFunctionCallABIStreaming(CGM, CallLoc, Caller, Callee);
checkFunctionCallABISoftFloat(CGM, CallLoc, Caller, Callee, Args, ReturnType);
}

void AArch64ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr,
unsigned Index,
raw_ostream &Out) const {
Expand Down
16 changes: 11 additions & 5 deletions clang/lib/CodeGen/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1482,8 +1482,8 @@ class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {

void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc,
const FunctionDecl *Caller,
const FunctionDecl *Callee,
const CallArgList &Args) const override;
const FunctionDecl *Callee, const CallArgList &Args,
QualType ReturnType) const override;
};
} // namespace

Expand Down Expand Up @@ -1558,9 +1558,15 @@ static bool checkAVXParam(DiagnosticsEngine &Diag, ASTContext &Ctx,
return false;
}

void X86_64TargetCodeGenInfo::checkFunctionCallABI(
CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller,
const FunctionDecl *Callee, const CallArgList &Args) const {
void X86_64TargetCodeGenInfo::checkFunctionCallABI(CodeGenModule &CGM,
SourceLocation CallLoc,
const FunctionDecl *Caller,
const FunctionDecl *Callee,
const CallArgList &Args,
QualType ReturnType) const {
if (!Callee)
return;

llvm::StringMap<bool> CallerMap;
llvm::StringMap<bool> CalleeMap;
unsigned ArgIndex = 0;
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,9 +564,9 @@ static llvm::Triple computeTargetTriple(const Driver &D,
StringRef ObjectMode = *ObjectModeValue;
llvm::Triple::ArchType AT = llvm::Triple::UnknownArch;

if (ObjectMode.equals("64")) {
if (ObjectMode == "64") {
AT = Target.get64BitArchVariant().getArch();
} else if (ObjectMode.equals("32")) {
} else if (ObjectMode == "32") {
AT = Target.get32BitArchVariant().getArch();
} else {
D.Diag(diag::err_drv_invalid_object_mode) << ObjectMode;
Expand Down Expand Up @@ -6694,7 +6694,7 @@ llvm::StringRef clang::driver::getDriverMode(StringRef ProgName,
return Opt.consume_front(OptName) ? Opt : "";
}

bool driver::IsClangCL(StringRef DriverMode) { return DriverMode.equals("cl"); }
bool driver::IsClangCL(StringRef DriverMode) { return DriverMode == "cl"; }

llvm::Error driver::expandResponseFiles(SmallVectorImpl<const char *> &Args,
bool ClangCLMode,
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Driver/OffloadBundler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,11 @@ bool OffloadTargetInfo::isOffloadKindValid() const {

bool OffloadTargetInfo::isOffloadKindCompatible(
const StringRef TargetOffloadKind) const {
if (OffloadKind == TargetOffloadKind)
if ((OffloadKind == TargetOffloadKind) ||
(OffloadKind == "hip" && TargetOffloadKind == "hipv4") ||
(OffloadKind == "hipv4" && TargetOffloadKind == "hip"))
return true;

if (BundlerConfig.HipOpenmpCompatible) {
bool HIPCompatibleWithOpenMP = OffloadKind.starts_with_insensitive("hip") &&
TargetOffloadKind == "openmp";
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/AIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,8 @@ static void addTocDataOptions(const llvm::opt::ArgList &Args,

// Currently only supported for small code model.
if (TOCDataGloballyinEffect &&
(Args.getLastArgValue(options::OPT_mcmodel_EQ).equals("large") ||
Args.getLastArgValue(options::OPT_mcmodel_EQ).equals("medium"))) {
(Args.getLastArgValue(options::OPT_mcmodel_EQ) == "large" ||
Args.getLastArgValue(options::OPT_mcmodel_EQ) == "medium")) {
D.Diag(clang::diag::warn_drv_unsupported_tocdata);
return;
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,7 @@ AMDGPUToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,

checkTargetID(*DAL);

if (!Args.getLastArgValue(options::OPT_x).equals("cl"))
if (Args.getLastArgValue(options::OPT_x) != "cl")
return DAL;

// Phase 1 (.cl -> .bc)
Expand Down
Loading