16 changes: 16 additions & 0 deletions clang/cmake/caches/Fuchsia.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,25 @@ set(_FUCHSIA_BOOTSTRAP_PASSTHROUGH
CURL_ROOT
OpenSSL_ROOT
httplib_ROOT

# Deprecated
CursesAndPanel_ROOT

CURSES_INCLUDE_DIRS
CURSES_LIBRARIES
PANEL_LIBRARIES

# Deprecated
Terminfo_ROOT

Terminfo_LIBRARIES

# Deprecated
LibEdit_ROOT

LibEdit_INCLUDE_DIRS
LibEdit_LIBRARIES

FUCHSIA_ENABLE_LLDB
LLDB_ENABLE_CURSES
LLDB_ENABLE_LIBEDIT
Expand Down
68 changes: 68 additions & 0 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,23 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

.. code-block:: c++

true:
unsigned i;
int &r;
int *p;
int (*f)();
false:
unsigned i;
int &r;
int *p;
int (*f)();
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
Expand Down Expand Up @@ -517,6 +534,23 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

.. code-block:: c++

true:
unsigned i;
int &r;
int *p;
int (*f)();
false:
unsigned i;
int &r;
int *p;
int (*f)();
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
Expand Down Expand Up @@ -642,6 +676,23 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

.. code-block:: c++

true:
unsigned i;
int &r;
int *p;
int (*f)();
false:
unsigned i;
int &r;
int *p;
int (*f)();
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
Expand Down Expand Up @@ -768,6 +819,23 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

.. code-block:: c++

true:
unsigned i;
int &r;
int *p;
int (*f)();
false:
unsigned i;
int &r;
int *p;
int (*f)();
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
Expand Down
2 changes: 1 addition & 1 deletion clang/docs/HLSL/FunctionCalls.rst
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ undefined behavior in HLSL, and any use of the argument after the call is a use
of an undefined value which may be illegal in the target (DXIL programs with
used or potentially used ``undef`` or ``poison`` values fail validation).

Clang Implementation
Clang Implementation
====================

.. note::
Expand Down
2 changes: 1 addition & 1 deletion clang/docs/InternalsManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ the option appears on the command line, the argument value is simply copied.
.. code-block:: text
def isysroot : JoinedOrSeparate<["-"], "isysroot">,
Visibility<[ClangOption, CC1Option]>,
Visibility<[ClangOption, CC1Option, FlangOption]>,
MarshallingInfoString<HeaderSearchOpts<"Sysroot">, [{"/"}]>;
**List of Strings**
Expand Down
2 changes: 2 additions & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,7 @@ to ``float``; see below for more information on this emulation.
see below.

* ``_Float16`` is supported on the following targets:

* 32-bit ARM (natively on some architecture versions)
* 64-bit ARM (AArch64) (natively on ARMv8.2a and above)
* AMDGPU (natively)
Expand All @@ -837,6 +838,7 @@ to ``float``; see below for more information on this emulation.
* RISC-V (natively if Zfh or Zhinx is available)

* ``__bf16`` is supported on the following targets (currently never natively):

* 32-bit ARM
* 64-bit ARM (AArch64)
* RISC-V
Expand Down
5 changes: 4 additions & 1 deletion clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,9 @@ Bug Fixes in This Version
- Clang now emits correct source location for code-coverage regions in `if constexpr`
and `if consteval` branches.
Fixes (`#54419 <https://github.com/llvm/llvm-project/issues/54419>`_)

- Fix an issue where clang cannot find conversion function with template
parameter when instantiation of template class.
Fixes (`#77583 <https://github.com/llvm/llvm-project/issues/77583>`_)

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -1099,6 +1101,7 @@ clang-format
- Add ``ObjCPropertyAttributeOrder`` which can be used to sort ObjC property
attributes (like ``nonatomic, strong, nullable``).
- Add ``.clang-format-ignore`` files.
- Add ``AlignFunctionPointers`` sub-option for ``AlignConsecutiveDeclarations``.

libclang
--------
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ ENUM_LANGOPT(SignReturnAddressKey, SignReturnAddressKeyKind, 1, SignReturnAddres
"Key used for return address signing")
LANGOPT(BranchTargetEnforcement, 1, 0, "Branch-target enforcement enabled")
LANGOPT(BranchProtectionPAuthLR, 1, 0, "Use PC as a diversifier using PAuthLR NOP instructions.")
LANGOPT(GuardedControlStack, 1, 0, "Guarded control stack enabled")

LANGOPT(SpeculativeLoadHardening, 1, 0, "Speculative load hardening enabled")

Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/OpenACCKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ enum class OpenACCClauseKind {
If,
/// 'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
Self,
/// 'copy' clause, allowed on Compute and Combined Constructs, plus 'data' and
/// 'declare'.
Copy,
/// 'use_device' clause, allowed on 'host_data' construct.
UseDevice,
/// Represents an invalid clause, for the purposes of parsing.
Invalid,
};
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1373,6 +1373,7 @@ class TargetInfo : public TransferrableTargetInfo,
LangOptions::SignReturnAddressKeyKind::AKey;
bool BranchTargetEnforcement = false;
bool BranchProtectionPAuthLR = false;
bool GuardedControlStack = false;
};

/// Determine if the Architecture in this TargetInfo supports branch
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4267,7 +4267,7 @@ def iquote : JoinedOrSeparate<["-"], "iquote">, Group<clang_i_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Add directory to QUOTE include search path">, MetaVarName<"<directory>">;
def isysroot : JoinedOrSeparate<["-"], "isysroot">, Group<clang_i_Group>,
Visibility<[ClangOption, CC1Option]>,
Visibility<[ClangOption, CC1Option, FlangOption]>,
HelpText<"Set the system root directory (usually /)">, MetaVarName<"<dir>">,
MarshallingInfoString<HeaderSearchOpts<"Sysroot">, [{"/"}]>;
def isystem : JoinedOrSeparate<["-"], "isystem">, Group<clang_i_Group>,
Expand Down Expand Up @@ -7012,6 +7012,8 @@ def mbranch_target_enforce : Flag<["-"], "mbranch-target-enforce">,
MarshallingInfoFlag<LangOpts<"BranchTargetEnforcement">>;
def mbranch_protection_pauth_lr : Flag<["-"], "mbranch-protection-pauth-lr">,
MarshallingInfoFlag<LangOpts<"BranchProtectionPAuthLR">>;
def mguarded_control_stack : Flag<["-"], "mguarded-control-stack">,
MarshallingInfoFlag<LangOpts<"GuardedControlStack">>;
def fno_dllexport_inlines : Flag<["-"], "fno-dllexport-inlines">,
MarshallingInfoNegativeFlag<LangOpts<"DllExportInlines">>;
def cfguard_no_checks : Flag<["-"], "cfguard-no-checks">,
Expand Down
21 changes: 20 additions & 1 deletion clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,22 @@ struct FormatStyle {
/// bbb = 2;
/// \endcode
bool AlignCompound;
/// Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
/// aligned.
/// \code
/// true:
/// unsigned i;
/// int &r;
/// int *p;
/// int (*f)();
///
/// false:
/// unsigned i;
/// int &r;
/// int *p;
/// int (*f)();
/// \endcode
bool AlignFunctionPointers;
/// Only for ``AlignConsecutiveAssignments``. Whether short assignment
/// operators are left-padded to the same length as long ones in order to
/// put all assignment operators to the right of the left hand side.
Expand All @@ -247,7 +263,9 @@ struct FormatStyle {
bool operator==(const AlignConsecutiveStyle &R) const {
return Enabled == R.Enabled && AcrossEmptyLines == R.AcrossEmptyLines &&
AcrossComments == R.AcrossComments &&
AlignCompound == R.AlignCompound && PadOperators == R.PadOperators;
AlignCompound == R.AlignCompound &&
AlignFunctionPointers == R.AlignFunctionPointers &&
PadOperators == R.PadOperators;
}
bool operator!=(const AlignConsecutiveStyle &R) const {
return !(*this == R);
Expand Down Expand Up @@ -3037,6 +3055,7 @@ struct FormatStyle {
bool isProto() const {
return Language == LK_Proto || Language == LK_TextProto;
}
bool isTableGen() const { return Language == LK_TableGen; }

/// Language, this format style is targeted at.
/// \version 3.5
Expand Down
11 changes: 11 additions & 0 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_PARSE_PARSER_H
#define LLVM_CLANG_PARSE_PARSER_H

#include "clang/Basic/OpenACCKinds.h"
#include "clang/Basic/OperatorPrecedence.h"
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/Preprocessor.h"
Expand Down Expand Up @@ -3568,6 +3569,16 @@ class Parser : public CodeCompletionHandler {
void ParseOpenACCCacheVarList();
/// Parses a single variable in a variable list for OpenACC.
bool ParseOpenACCVar();
/// Parses the variable list for the variety of clauses that take a var-list,
/// including the optional Special Token listed for some,based on clause type.
bool ParseOpenACCClauseVarList(OpenACCClauseKind Kind);
/// Parses any parameters for an OpenACC Clause, including required/optional
/// parens.
bool ParseOpenACCClauseParams(OpenACCClauseKind Kind);
/// Parses a single clause in a clause-list for OpenACC.
bool ParseOpenACCClause();
/// Parses the clause-list for an OpenACC directive.
void ParseOpenACCClauseList();
bool ParseOpenACCWaitArgument();

private:
Expand Down
24 changes: 17 additions & 7 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5929,15 +5929,22 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
if (ToD)
return ToD;

bool IsFriendTemplate = D->getFriendObjectKind() != Decl::FOK_None;
bool IsDependentContext = DC != LexicalDC ? LexicalDC->isDependentContext()
: DC->isDependentContext();
bool DependentFriend = IsFriendTemplate && IsDependentContext;
// Should check if a declaration is friend in a dependent context.
// Such templates are not linked together in a declaration chain.
// The ASTImporter strategy is to map existing forward declarations to
// imported ones only if strictly necessary, otherwise import these as new
// forward declarations. In case of the "dependent friend" declarations, new
// declarations are created, but not linked in a declaration chain.
auto IsDependentFriend = [](ClassTemplateDecl *TD) {
return TD->getFriendObjectKind() != Decl::FOK_None &&
TD->getLexicalDeclContext()->isDependentContext();
};
bool DependentFriend = IsDependentFriend(D);

ClassTemplateDecl *FoundByLookup = nullptr;

// We may already have a template of the same name; try to find and match it.
if (!DependentFriend && !DC->isFunctionOrMethod()) {
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
Expand All @@ -5953,10 +5960,13 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {

// FIXME: sufficient conditon for 'IgnoreTemplateParmDepth'?
bool IgnoreTemplateParmDepth =
FoundTemplate->getFriendObjectKind() != Decl::FOK_None &&
!D->specializations().empty();
(FoundTemplate->getFriendObjectKind() != Decl::FOK_None) !=
(D->getFriendObjectKind() != Decl::FOK_None);
if (IsStructuralMatch(D, FoundTemplate, /*Complain=*/true,
IgnoreTemplateParmDepth)) {
if (DependentFriend || IsDependentFriend(FoundTemplate))
continue;

ClassTemplateDecl *TemplateWithDef =
getTemplateDefinition(FoundTemplate);
if (D->isThisDeclarationADefinition() && TemplateWithDef)
Expand Down
12 changes: 12 additions & 0 deletions clang/lib/AST/Interp/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,18 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC) {
if (CurFunc->isUnevaluatedBuiltin())
return;

// Some builtin functions require us to only look at the call site, since
// the classified parameter types do not match.
if (CurFunc->isBuiltin()) {
const auto *CE =
cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
const Expr *A = CE->getArg(I);
popArg(S, A);
}
return;
}

if (S.Current->Caller && CurFunc->isVariadic()) {
// CallExpr we're look for is at the return PC of the current function, i.e.
// in the caller.
Expand Down
33 changes: 30 additions & 3 deletions clang/lib/AST/Interp/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ static bool retPrimValue(InterpState &S, CodePtr OpPC, APValue &Result,
case X: \
return Ret<X>(S, OpPC, Result);
switch (*T) {
RET_CASE(PT_Ptr);
RET_CASE(PT_FnPtr);
RET_CASE(PT_Float);
RET_CASE(PT_Bool);
RET_CASE(PT_Sint8);
Expand Down Expand Up @@ -613,15 +615,34 @@ static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC,
return true;
}

static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
PrimType PtrT =
S.getContext().classify(Call->getArg(0)->getType()).value_or(PT_Ptr);

if (PtrT == PT_FnPtr) {
const FunctionPointer &Arg = S.Stk.peek<FunctionPointer>();
S.Stk.push<FunctionPointer>(Arg);
} else if (PtrT == PT_Ptr) {
const Pointer &Arg = S.Stk.peek<Pointer>();
S.Stk.push<Pointer>(Arg);
} else {
assert(false && "Unsupported pointer type passed to __builtin_addressof()");
}
return true;
}

bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
const CallExpr *Call) {
InterpFrame *Frame = S.Current;
APValue Dummy;

QualType ReturnType = Call->getCallReturnType(S.getCtx());
std::optional<PrimType> ReturnT = S.getContext().classify(ReturnType);
std::optional<PrimType> ReturnT = S.getContext().classify(Call->getType());

// If classify failed, we assume void.
assert(ReturnT || ReturnType->isVoidType());
assert(ReturnT || Call->getType()->isVoidType());

switch (F->getBuiltinID()) {
case Builtin::BI__builtin_is_constant_evaluated:
Expand Down Expand Up @@ -820,6 +841,12 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
if (!interp__builtin_ffs(S, OpPC, Frame, F, Call))
return false;
break;
case Builtin::BIaddressof:
case Builtin::BI__addressof:
case Builtin::BI__builtin_addressof:
if (!interp__builtin_addressof(S, OpPC, Frame, F, Call))
return false;
break;

default:
return false;
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,

BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement;
BPI.BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR;
BPI.GuardedControlStack = PBP.GuardedControlStack;
return true;
}

Expand Down Expand Up @@ -532,6 +533,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
if (Opts.BranchTargetEnforcement)
Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1");

if (Opts.GuardedControlStack)
Builder.defineMacro("__ARM_FEATURE_GCS_DEFAULT", "1");

if (HasLS64)
Builder.defineMacro("__ARM_FEATURE_LS64", "1");

Expand All @@ -544,6 +548,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
if (HasD128)
Builder.defineMacro("__ARM_FEATURE_SYSREG128", "1");

if (HasGCS)
Builder.defineMacro("__ARM_FEATURE_GCS", "1");

if (*ArchInfo == llvm::AArch64::ARMV8_1A)
getTargetDefinesARMV81A(Opts, Builder);
else if (*ArchInfo == llvm::AArch64::ARMV8_2A)
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/Basic/Targets/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,8 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
auto ExtName = Extension.first;
auto ExtInfo = Extension.second;

Builder.defineMacro(
Twine("__riscv_", ExtName),
Twine(getVersionValue(ExtInfo.MajorVersion, ExtInfo.MinorVersion)));
Builder.defineMacro(Twine("__riscv_", ExtName),
Twine(getVersionValue(ExtInfo.Major, ExtInfo.Minor)));
}

if (ISAInfo->hasExtension("m") || ISAInfo->hasExtension("zmmul"))
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2612,6 +2612,8 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
if (IRFunctionArgs.hasSRetArg()) {
llvm::AttrBuilder SRETAttrs(getLLVMContext());
SRETAttrs.addStructRetAttr(getTypes().ConvertTypeForMem(RetTy));
SRETAttrs.addAttribute(llvm::Attribute::Writable);
SRETAttrs.addAttribute(llvm::Attribute::DeadOnUnwind);
hasUsedSRet = true;
if (RetAI.getInReg())
SRETAttrs.addAttribute(llvm::Attribute::InReg);
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,8 @@ void CodeGenModule::Release() {
if (LangOpts.BranchProtectionPAuthLR)
getModule().addModuleFlag(llvm::Module::Min, "branch-protection-pauth-lr",
1);
if (LangOpts.GuardedControlStack)
getModule().addModuleFlag(llvm::Module::Min, "guarded-control-stack", 1);
if (LangOpts.hasSignReturnAddress())
getModule().addModuleFlag(llvm::Module::Min, "sign-return-address", 1);
if (LangOpts.isSignReturnAddressScopeAll())
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
BPI.BranchTargetEnforcement ? "true" : "false");
Fn->addFnAttr("branch-protection-pauth-lr",
BPI.BranchProtectionPAuthLR ? "true" : "false");
Fn->addFnAttr("guarded-control-stack",
BPI.GuardedControlStack ? "true" : "false");
}

bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF,
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1508,7 +1508,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args,
<< Triple.getArchName();

StringRef Scope, Key;
bool IndirectBranches, BranchProtectionPAuthLR;
bool IndirectBranches, BranchProtectionPAuthLR, GuardedControlStack;

if (A->getOption().matches(options::OPT_msign_return_address_EQ)) {
Scope = A->getValue();
Expand All @@ -1518,6 +1518,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args,
Key = "a_key";
IndirectBranches = false;
BranchProtectionPAuthLR = false;
GuardedControlStack = false;
} else {
StringRef DiagMsg;
llvm::ARM::ParsedBranchProtection PBP;
Expand All @@ -1531,6 +1532,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args,
Key = PBP.Key;
BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR;
IndirectBranches = PBP.BranchTargetEnforcement;
GuardedControlStack = PBP.GuardedControlStack;
}

CmdArgs.push_back(
Expand All @@ -1543,6 +1545,8 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args,
Args.MakeArgString(Twine("-mbranch-protection-pauth-lr")));
if (IndirectBranches)
CmdArgs.push_back("-mbranch-target-enforce");
if (GuardedControlStack)
CmdArgs.push_back("-mguarded-control-stack");
}

void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,12 +403,10 @@ void Flang::addTargetOptions(const ArgList &Args,
if (A->getValue() == StringRef{"Accelerate"}) {
CmdArgs.push_back("-framework");
CmdArgs.push_back("Accelerate");
A->render(Args, CmdArgs);
}
}
} else {
A->render(Args, CmdArgs);
}
A->render(Args, CmdArgs);
}

if (Triple.isKnownWindowsMSVCEnvironment()) {
Expand Down
30 changes: 15 additions & 15 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,48 +76,47 @@ template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/false, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*PadOperators=*/true}));
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
IO.enumCase(Value, "Consecutive",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*PadOperators=*/true}));
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
IO.enumCase(Value, "AcrossEmptyLines",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/true,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*PadOperators=*/true}));
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
IO.enumCase(Value, "AcrossComments",
FormatStyle::AlignConsecutiveStyle({/*Enabled=*/true,
/*AcrossEmptyLines=*/false,
/*AcrossComments=*/true,
/*AlignCompound=*/false,
/*PadOperators=*/true}));
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/true, /*AlignCompound=*/false,
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
IO.enumCase(Value, "AcrossEmptyLinesAndComments",
FormatStyle::AlignConsecutiveStyle({/*Enabled=*/true,
/*AcrossEmptyLines=*/true,
/*AcrossComments=*/true,
/*AlignCompound=*/false,
/*PadOperators=*/true}));
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/true,
/*AcrossComments=*/true, /*AlignCompound=*/false,
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));

// For backward compatibility.
IO.enumCase(Value, "true",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*PadOperators=*/true}));
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
IO.enumCase(Value, "false",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/false, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*PadOperators=*/true}));
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
}

static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
IO.mapOptional("Enabled", Value.Enabled);
IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
IO.mapOptional("AcrossComments", Value.AcrossComments);
IO.mapOptional("AlignCompound", Value.AlignCompound);
IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers);
IO.mapOptional("PadOperators", Value.PadOperators);
}
};
Expand Down Expand Up @@ -1432,6 +1431,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;
LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false;
LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false;
LLVMStyle.AlignConsecutiveAssignments.AlignFunctionPointers = false;
LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
LLVMStyle.AlignConsecutiveBitFields = {};
LLVMStyle.AlignConsecutiveDeclarations = {};
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Format/FormatToken.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ unsigned CommaSeparatedList::formatAfterToken(LineState &State,
if (!State.NextToken || !State.NextToken->Previous)
return 0;

if (Formats.size() == 1)
return 0; // Handled by formatFromToken
if (Formats.size() <= 1)
return 0; // Handled by formatFromToken (1) or avoid severe penalty (0).

// Ensure that we start on the opening brace.
const FormatToken *LBrace =
Expand Down
100 changes: 92 additions & 8 deletions clang/lib/Format/FormatToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,14 +275,15 @@ class AnnotatedLine;
struct FormatToken {
FormatToken()
: HasUnescapedNewline(false), IsMultiline(false), IsFirst(false),
MustBreakBefore(false), IsUnterminatedLiteral(false),
CanBreakBefore(false), ClosesTemplateDeclaration(false),
StartsBinaryExpression(false), EndsBinaryExpression(false),
PartOfMultiVariableDeclStmt(false), ContinuesLineCommentSection(false),
Finalized(false), ClosesRequiresClause(false),
EndsCppAttributeGroup(false), BlockKind(BK_Unknown),
Decision(FD_Unformatted), PackingKind(PPK_Inconclusive),
TypeIsFinalized(false), Type(TT_Unknown) {}
MustBreakBefore(false), MustBreakBeforeFinalized(false),
IsUnterminatedLiteral(false), CanBreakBefore(false),
ClosesTemplateDeclaration(false), StartsBinaryExpression(false),
EndsBinaryExpression(false), PartOfMultiVariableDeclStmt(false),
ContinuesLineCommentSection(false), Finalized(false),
ClosesRequiresClause(false), EndsCppAttributeGroup(false),
BlockKind(BK_Unknown), Decision(FD_Unformatted),
PackingKind(PPK_Inconclusive), TypeIsFinalized(false),
Type(TT_Unknown) {}

/// The \c Token.
Token Tok;
Expand Down Expand Up @@ -318,6 +319,10 @@ struct FormatToken {
/// before the token.
unsigned MustBreakBefore : 1;

/// Whether MustBreakBefore is finalized during parsing and must not
/// be reset between runs.
unsigned MustBreakBeforeFinalized : 1;

/// Set to \c true if this token is an unterminated literal.
unsigned IsUnterminatedLiteral : 1;

Expand Down Expand Up @@ -416,10 +421,14 @@ struct FormatToken {
/// to another one please use overwriteFixedType, or even better remove the
/// need to reassign the type.
void setFinalizedType(TokenType T) {
if (MacroCtx && MacroCtx->Role == MR_UnexpandedArg)
return;
Type = T;
TypeIsFinalized = true;
}
void overwriteFixedType(TokenType T) {
if (MacroCtx && MacroCtx->Role == MR_UnexpandedArg)
return;
TypeIsFinalized = false;
setType(T);
}
Expand Down Expand Up @@ -1202,6 +1211,21 @@ struct AdditionalKeywords {
kw_verilogHashHash = &IdentTable.get("##");
kw_apostrophe = &IdentTable.get("\'");

// TableGen keywords
kw_bit = &IdentTable.get("bit");
kw_bits = &IdentTable.get("bits");
kw_code = &IdentTable.get("code");
kw_dag = &IdentTable.get("dag");
kw_def = &IdentTable.get("def");
kw_defm = &IdentTable.get("defm");
kw_defset = &IdentTable.get("defset");
kw_defvar = &IdentTable.get("defvar");
kw_dump = &IdentTable.get("dump");
kw_include = &IdentTable.get("include");
kw_list = &IdentTable.get("list");
kw_multiclass = &IdentTable.get("multiclass");
kw_then = &IdentTable.get("then");

// Keep this at the end of the constructor to make sure everything here
// is
// already initialized.
Expand Down Expand Up @@ -1294,6 +1318,27 @@ struct AdditionalKeywords {
kw_wildcard, kw_wire,
kw_with, kw_wor,
kw_verilogHash, kw_verilogHashHash});

TableGenExtraKeywords = std::unordered_set<IdentifierInfo *>({
kw_assert,
kw_bit,
kw_bits,
kw_code,
kw_dag,
kw_def,
kw_defm,
kw_defset,
kw_defvar,
kw_dump,
kw_foreach,
kw_in,
kw_include,
kw_let,
kw_list,
kw_multiclass,
kw_string,
kw_then,
});
}

// Context sensitive keywords.
Expand Down Expand Up @@ -1539,6 +1584,21 @@ struct AdditionalKeywords {
// Symbols in Verilog that don't exist in C++.
IdentifierInfo *kw_apostrophe;

// TableGen keywords
IdentifierInfo *kw_bit;
IdentifierInfo *kw_bits;
IdentifierInfo *kw_code;
IdentifierInfo *kw_dag;
IdentifierInfo *kw_def;
IdentifierInfo *kw_defm;
IdentifierInfo *kw_defset;
IdentifierInfo *kw_defvar;
IdentifierInfo *kw_dump;
IdentifierInfo *kw_include;
IdentifierInfo *kw_list;
IdentifierInfo *kw_multiclass;
IdentifierInfo *kw_then;

/// Returns \c true if \p Tok is a keyword or an identifier.
bool isWordLike(const FormatToken &Tok) const {
// getIdentifierinfo returns non-null for keywords as well as identifiers.
Expand Down Expand Up @@ -1811,6 +1871,27 @@ struct AdditionalKeywords {
}
}

bool isTableGenDefinition(const FormatToken &Tok) const {
return Tok.isOneOf(kw_def, kw_defm, kw_defset, kw_defvar, kw_multiclass,
kw_let, tok::kw_class);
}

bool isTableGenKeyword(const FormatToken &Tok) const {
switch (Tok.Tok.getKind()) {
case tok::kw_class:
case tok::kw_else:
case tok::kw_false:
case tok::kw_if:
case tok::kw_int:
case tok::kw_true:
return true;
default:
return Tok.is(tok::identifier) &&
TableGenExtraKeywords.find(Tok.Tok.getIdentifierInfo()) !=
TableGenExtraKeywords.end();
}
}

private:
/// The JavaScript keywords beyond the C++ keyword set.
std::unordered_set<IdentifierInfo *> JsExtraKeywords;
Expand All @@ -1820,6 +1901,9 @@ struct AdditionalKeywords {

/// The Verilog keywords beyond the C++ keyword set.
std::unordered_set<IdentifierInfo *> VerilogExtraKeywords;

/// The TableGen keywords beyond the C++ keyword set.
std::unordered_set<IdentifierInfo *> TableGenExtraKeywords;
};

inline bool isLineComment(const FormatToken &FormatTok) {
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Format/FormatTokenLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,9 @@ FormatToken *FormatTokenLexer::getNextToken() {
tok::kw_operator)) {
FormatTok->Tok.setKind(tok::identifier);
FormatTok->Tok.setIdentifierInfo(nullptr);
} else if (Style.isTableGen() && !Keywords.isTableGenKeyword(*FormatTok)) {
FormatTok->Tok.setKind(tok::identifier);
FormatTok->Tok.setIdentifierInfo(nullptr);
}
} else if (FormatTok->is(tok::greatergreater)) {
FormatTok->Tok.setKind(tok::greater);
Expand Down
20 changes: 13 additions & 7 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2234,6 +2234,12 @@ class AnnotatingParser {
if (PreviousNotConst->ClosesRequiresClause)
return false;

if (Style.isTableGen()) {
// keywords such as let and def* defines names.
if (Keywords.isTableGenDefinition(*PreviousNotConst))
return true;
}

bool IsPPKeyword = PreviousNotConst->is(tok::identifier) &&
PreviousNotConst->Previous &&
PreviousNotConst->Previous->is(tok::hash);
Expand Down Expand Up @@ -2769,13 +2775,6 @@ class ExpressionParser {
// Consume operators with higher precedence.
parse(Precedence + 1);

// Do not assign fake parenthesis to tokens that are part of an
// unexpanded macro call. The line within the macro call contains
// the parenthesis and commas, and we will not find operators within
// that structure.
if (Current && Current->MacroParent)
break;

int CurrentPrecedence = getCurrentPrecedence();

if (Precedence == CurrentPrecedence && Current &&
Expand Down Expand Up @@ -2919,6 +2918,13 @@ class ExpressionParser {

void addFakeParenthesis(FormatToken *Start, prec::Level Precedence,
FormatToken *End = nullptr) {
// Do not assign fake parenthesis to tokens that are part of an
// unexpanded macro call. The line within the macro call contains
// the parenthesis and commas, and we will not find operators within
// that structure.
if (Start->MacroParent)
return;

Start->FakeLParens.push_back(Precedence);
if (Precedence > prec::Unknown)
Start->StartsBinaryExpression = true;
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/Format/UnwrappedLineFormatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -954,13 +954,15 @@ static void markFinalized(FormatToken *Tok) {
// will be modified as unexpanded arguments (as part of the macro call
// formatting) in the next pass.
Tok->MacroCtx->Role = MR_UnexpandedArg;
// Reset whether spaces are required before this token, as that is context
// dependent, and that context may change when formatting the macro call.
// For example, given M(x) -> 2 * x, and the macro call M(var),
// the token 'var' will have SpacesRequiredBefore = 1 after being
// Reset whether spaces or a line break are required before this token, as
// that is context dependent, and that context may change when formatting
// the macro call. For example, given M(x) -> 2 * x, and the macro call
// M(var), the token 'var' will have SpacesRequiredBefore = 1 after being
// formatted as part of the expanded macro, but SpacesRequiredBefore = 0
// for its position within the macro call.
Tok->SpacesRequiredBefore = 0;
if (!Tok->MustBreakBeforeFinalized)
Tok->MustBreakBefore = 0;
} else {
Tok->Finalized = true;
}
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2308,7 +2308,7 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
LeftSquare->isCppStructuredBinding(Style)) {
return false;
}
if (FormatTok->is(tok::l_square))
if (FormatTok->is(tok::l_square) || tok::isLiteral(FormatTok->Tok.getKind()))
return false;
if (FormatTok->is(tok::r_square)) {
const FormatToken *Next = Tokens->peekNextToken(/*SkipComment=*/true);
Expand Down Expand Up @@ -4675,6 +4675,7 @@ void UnwrappedLineParser::readToken(int LevelDifference) {
conditionalCompilationEnd();
FormatTok = Tokens->getNextToken();
FormatTok->MustBreakBefore = true;
FormatTok->MustBreakBeforeFinalized = true;
}

auto IsFirstNonCommentOnLine = [](bool FirstNonCommentOnLine,
Expand Down Expand Up @@ -4891,6 +4892,7 @@ void UnwrappedLineParser::pushToken(FormatToken *Tok) {
Line->Tokens.push_back(UnwrappedLineNode(Tok));
if (MustBreakBeforeNextToken) {
Line->Tokens.back().Tok->MustBreakBefore = true;
Line->Tokens.back().Tok->MustBreakBeforeFinalized = true;
MustBreakBeforeNextToken = false;
}
}
Expand Down
9 changes: 8 additions & 1 deletion clang/lib/Format/WhitespaceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,14 @@ void WhitespaceManager::alignConsecutiveDeclarations() {

AlignTokens(
Style,
[](Change const &C) {
[&](Change const &C) {
if (Style.AlignConsecutiveDeclarations.AlignFunctionPointers) {
for (const auto *Prev = C.Tok->Previous; Prev; Prev = Prev->Previous)
if (Prev->is(tok::equal))
return false;
if (C.Tok->is(TT_FunctionTypeLParen))
return true;
}
if (C.Tok->is(TT_FunctionDeclarationName))
return true;
if (C.Tok->isNot(TT_StartOfName))
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/WhitespaceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ class WhitespaceManager {
for (auto PrevIter = Start; PrevIter != End; ++PrevIter) {
// If we broke the line the initial spaces are already
// accounted for.
assert(PrevIter->Index < Changes.size());
if (Changes[PrevIter->Index].NewlinesBefore > 0)
NetWidth = 0;
NetWidth +=
Expand Down
166 changes: 98 additions & 68 deletions clang/lib/Parse/ParseOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
return llvm::StringSwitch<OpenACCClauseKind>(
Tok.getIdentifierInfo()->getName())
.Case("auto", OpenACCClauseKind::Auto)
.Case("copy", OpenACCClauseKind::Copy)
.Case("default", OpenACCClauseKind::Default)
.Case("finalize", OpenACCClauseKind::Finalize)
.Case("if", OpenACCClauseKind::If)
Expand All @@ -98,6 +99,7 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
.Case("nohost", OpenACCClauseKind::NoHost)
.Case("self", OpenACCClauseKind::Self)
.Case("seq", OpenACCClauseKind::Seq)
.Case("use_device", OpenACCClauseKind::UseDevice)
.Case("vector", OpenACCClauseKind::Vector)
.Case("worker", OpenACCClauseKind::Worker)
.Default(OpenACCClauseKind::Invalid);
Expand Down Expand Up @@ -334,7 +336,9 @@ bool ClauseHasOptionalParens(OpenACCClauseKind Kind) {
}

bool ClauseHasRequiredParens(OpenACCClauseKind Kind) {
return Kind == OpenACCClauseKind::Default || Kind == OpenACCClauseKind::If;
return Kind == OpenACCClauseKind::Default || Kind == OpenACCClauseKind::If ||
Kind == OpenACCClauseKind::Copy ||
Kind == OpenACCClauseKind::UseDevice;
}

ExprResult ParseOpenACCConditionalExpr(Parser &P) {
Expand All @@ -345,43 +349,125 @@ ExprResult ParseOpenACCConditionalExpr(Parser &P) {
return P.getActions().CorrectDelayedTyposInExpr(P.ParseExpression());
}

bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
BalancedDelimiterTracker Parens(P, tok::l_paren,
// Skip until we see the end of pragma token, but don't consume it. This is us
// just giving up on the rest of the pragma so we can continue executing. We
// have to do this because 'SkipUntil' considers paren balancing, which isn't
// what we want.
void SkipUntilEndOfDirective(Parser &P) {
while (P.getCurToken().isNot(tok::annot_pragma_openacc_end))
P.ConsumeAnyToken();
}

} // namespace

// OpenACC 3.3, section 1.7:
// To simplify the specification and convey appropriate constraint information,
// a pqr-list is a comma-separated list of pdr items. The one exception is a
// clause-list, which is a list of one or more clauses optionally separated by
// commas.
void Parser::ParseOpenACCClauseList() {
bool FirstClause = true;
while (getCurToken().isNot(tok::annot_pragma_openacc_end)) {
// Comma is optional in a clause-list.
if (!FirstClause && getCurToken().is(tok::comma))
ConsumeToken();
FirstClause = false;

// Recovering from a bad clause is really difficult, so we just give up on
// error.
if (ParseOpenACCClause()) {
SkipUntilEndOfDirective(*this);
return;
}
}
}

bool Parser::ParseOpenACCClauseVarList(OpenACCClauseKind Kind) {
// FIXME: Future clauses will require 'special word' parsing, check for one,
// then parse it based on whether it is a clause that requires a 'special
// word'.
(void)Kind;

// If the var parsing fails, skip until the end of the directive as this is
// an expression and gets messy if we try to continue otherwise.
if (ParseOpenACCVar())
return true;

while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
ExpectAndConsume(tok::comma);

// If the var parsing fails, skip until the end of the directive as this is
// an expression and gets messy if we try to continue otherwise.
if (ParseOpenACCVar())
return true;
}
return false;
}
// The OpenACC Clause List is a comma or space-delimited list of clauses (see
// the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't
// really have its owner grammar and each individual one has its own definition.
// However, they all are named with a single-identifier (or auto/default!)
// token, followed in some cases by either braces or parens.
bool Parser::ParseOpenACCClause() {
// A number of clause names are actually keywords, so accept a keyword that
// can be converted to a name.
if (expectIdentifierOrKeyword(*this))
return true;

OpenACCClauseKind Kind = getOpenACCClauseKind(getCurToken());

if (Kind == OpenACCClauseKind::Invalid)
return Diag(getCurToken(), diag::err_acc_invalid_clause)
<< getCurToken().getIdentifierInfo();

// Consume the clause name.
ConsumeToken();

return ParseOpenACCClauseParams(Kind);
}

bool Parser::ParseOpenACCClauseParams(OpenACCClauseKind Kind) {
BalancedDelimiterTracker Parens(*this, tok::l_paren,
tok::annot_pragma_openacc_end);

if (ClauseHasRequiredParens(Kind)) {
if (Parens.expectAndConsume()) {
// We are missing a paren, so assume that the person just forgot the
// parameter. Return 'false' so we try to continue on and parse the next
// clause.
P.SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
Parser::StopBeforeMatch);
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
Parser::StopBeforeMatch);
return false;
}

switch (Kind) {
case OpenACCClauseKind::Default: {
Token DefKindTok = P.getCurToken();
Token DefKindTok = getCurToken();

if (expectIdentifierOrKeyword(P))
if (expectIdentifierOrKeyword(*this))
break;

P.ConsumeToken();
ConsumeToken();

if (getOpenACCDefaultClauseKind(DefKindTok) ==
OpenACCDefaultClauseKind::Invalid)
P.Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);
Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);

break;
}
case OpenACCClauseKind::If: {
ExprResult CondExpr = ParseOpenACCConditionalExpr(P);
ExprResult CondExpr = ParseOpenACCConditionalExpr(*this);
// An invalid expression can be just about anything, so just give up on
// this clause list.
if (CondExpr.isInvalid())
return true;
break;
}
case OpenACCClauseKind::UseDevice:
case OpenACCClauseKind::Copy:
if (ParseOpenACCClauseVarList(Kind))
return true;
break;
default:
llvm_unreachable("Not a required parens type?");
}
Expand All @@ -391,7 +477,7 @@ bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
if (!Parens.consumeOpen()) {
switch (Kind) {
case OpenACCClauseKind::Self: {
ExprResult CondExpr = ParseOpenACCConditionalExpr(P);
ExprResult CondExpr = ParseOpenACCConditionalExpr(*this);
// An invalid expression can be just about anything, so just give up on
// this clause list.
if (CondExpr.isInvalid())
Expand All @@ -407,62 +493,6 @@ bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
return false;
}

// The OpenACC Clause List is a comma or space-delimited list of clauses (see
// the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't
// really have its owner grammar and each individual one has its own definition.
// However, they all are named with a single-identifier (or auto/default!)
// token, followed in some cases by either braces or parens.
bool ParseOpenACCClause(Parser &P) {
// A number of clause names are actually keywords, so accept a keyword that
// can be converted to a name.
if (expectIdentifierOrKeyword(P))
return true;

OpenACCClauseKind Kind = getOpenACCClauseKind(P.getCurToken());

if (Kind == OpenACCClauseKind::Invalid)
return P.Diag(P.getCurToken(), diag::err_acc_invalid_clause)
<< P.getCurToken().getIdentifierInfo();

// Consume the clause name.
P.ConsumeToken();

return ParseOpenACCClauseParams(P, Kind);
}

// Skip until we see the end of pragma token, but don't consume it. This is us
// just giving up on the rest of the pragma so we can continue executing. We
// have to do this because 'SkipUntil' considers paren balancing, which isn't
// what we want.
void SkipUntilEndOfDirective(Parser &P) {
while (P.getCurToken().isNot(tok::annot_pragma_openacc_end))
P.ConsumeAnyToken();
}

// OpenACC 3.3, section 1.7:
// To simplify the specification and convey appropriate constraint information,
// a pqr-list is a comma-separated list of pdr items. The one exception is a
// clause-list, which is a list of one or more clauses optionally separated by
// commas.
void ParseOpenACCClauseList(Parser &P) {
bool FirstClause = true;
while (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) {
// Comma is optional in a clause-list.
if (!FirstClause && P.getCurToken().is(tok::comma))
P.ConsumeToken();
FirstClause = false;

// Recovering from a bad clause is really difficult, so we just give up on
// error.
if (ParseOpenACCClause(P)) {
SkipUntilEndOfDirective(P);
return;
}
}
}

} // namespace

/// OpenACC 3.3, section 2.16:
/// In this section and throughout the specification, the term wait-argument
/// means:
Expand Down Expand Up @@ -664,7 +694,7 @@ void Parser::ParseOpenACCDirective() {
}

// Parses the list of clauses, if present.
ParseOpenACCClauseList(*this);
ParseOpenACCClauseList();

Diag(getCurToken(), diag::warn_pragma_acc_unimplemented);
assert(Tok.is(tok::annot_pragma_openacc_end) &&
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaExprMember.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,8 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
const Scope *S,
ActOnMemberAccessExtraArgs *ExtraArgs) {
if (BaseType->isDependentType() ||
(SS.isSet() && isDependentScopeSpecifier(SS)))
(SS.isSet() && isDependentScopeSpecifier(SS)) ||
NameInfo.getName().isDependentName())
return ActOnDependentMemberExpr(Base, BaseType,
IsArrow, OpLoc,
SS, TemplateKWLoc, FirstQualifierInScope,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2274,7 +2274,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
addToFunctionSummaryMap(
"ftell", Signature(ArgTypes{FilePtrTy}, RetType{LongTy}),
Summary(NoEvalCall)
.Case({ReturnValueCondition(WithinRange, Range(1, LongMax))},
.Case({ReturnValueCondition(WithinRange, Range(0, LongMax))},
ErrnoUnchanged, GenericSuccessMsg)
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg)
.ArgConstraint(NotNull(ArgNo(0))));
Expand Down
14 changes: 9 additions & 5 deletions clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,12 @@ class StreamChecker : public Checker<check::PreCall, eval::Call,
std::bind(&StreamChecker::evalUngetc, _1, _2, _3, _4), 1}},
{{{"fseek"}, 3},
{&StreamChecker::preFseek, &StreamChecker::evalFseek, 0}},
{{{"fseeko"}, 3},
{&StreamChecker::preFseek, &StreamChecker::evalFseek, 0}},
{{{"ftell"}, 1},
{&StreamChecker::preDefault, &StreamChecker::evalFtell, 0}},
{{{"ftello"}, 1},
{&StreamChecker::preDefault, &StreamChecker::evalFtell, 0}},
{{{"fflush"}, 1},
{&StreamChecker::preFflush, &StreamChecker::evalFflush, 0}},
{{{"rewind"}, 1},
Expand Down Expand Up @@ -1113,18 +1117,18 @@ void StreamChecker::evalFtell(const FnDescription *Desc, const CallEvent &Call,
NonLoc RetVal = makeRetVal(C, CE).castAs<NonLoc>();
ProgramStateRef StateNotFailed =
State->BindExpr(CE, C.getLocationContext(), RetVal);
auto Cond = SVB.evalBinOp(State, BO_GE, RetVal,
SVB.makeZeroVal(C.getASTContext().LongTy),
SVB.getConditionType())
.getAs<DefinedOrUnknownSVal>();
auto Cond =
SVB.evalBinOp(State, BO_GE, RetVal, SVB.makeZeroVal(Call.getResultType()),
SVB.getConditionType())
.getAs<DefinedOrUnknownSVal>();
if (!Cond)
return;
StateNotFailed = StateNotFailed->assume(*Cond, true);
if (!StateNotFailed)
return;

ProgramStateRef StateFailed = State->BindExpr(
CE, C.getLocationContext(), SVB.makeIntVal(-1, C.getASTContext().LongTy));
CE, C.getLocationContext(), SVB.makeIntVal(-1, Call.getResultType()));

// This function does not affect the stream state.
// Still we add success and failure state with the appropriate return value.
Expand Down
24 changes: 24 additions & 0 deletions clang/test/AST/Interp/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,3 +389,27 @@ namespace Packs {
static_assert(foo<int, char>() == 2, "");
static_assert(foo<>() == 0, "");
}

namespace AddressOf {
struct S {} s;
static_assert(__builtin_addressof(s) == &s, "");

struct T { constexpr T *operator&() const { return nullptr; } int n; } t;
constexpr T *pt = __builtin_addressof(t);
static_assert(&pt->n == &t.n, "");

struct U { int n : 5; } u;
int *pbf = __builtin_addressof(u.n); // expected-error {{address of bit-field requested}} \
// ref-error {{address of bit-field requested}}

S *ptmp = __builtin_addressof(S{}); // expected-error {{taking the address of a temporary}} \
// expected-warning {{temporary whose address is used as value of local variable 'ptmp' will be destroyed at the end of the full-expression}} \
// ref-error {{taking the address of a temporary}} \
// ref-warning {{temporary whose address is used as value of local variable 'ptmp' will be destroyed at the end of the full-expression}}

constexpr int foo() {return 1;}
static_assert(__builtin_addressof(foo) == foo, "");

constexpr _Complex float F = {3, 4};
static_assert(__builtin_addressof(F) == &F, "");
}
3 changes: 3 additions & 0 deletions clang/test/Analysis/Inputs/system-header-simulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ typedef __typeof(sizeof(int)) size_t;
typedef long long __int64_t;
typedef __int64_t __darwin_off_t;
typedef __darwin_off_t fpos_t;
typedef int off_t;

typedef struct _FILE FILE;
#define SEEK_SET 0 /* Seek from beginning of file. */
Expand Down Expand Up @@ -55,7 +56,9 @@ int fputc(int ch, FILE *stream);
int fputs(const char *restrict s, FILE *restrict stream);
int ungetc(int c, FILE *stream);
int fseek(FILE *__stream, long int __off, int __whence);
int fseeko(FILE *__stream, off_t __off, int __whence);
long int ftell(FILE *__stream);
off_t ftello(FILE *__stream);
void rewind(FILE *__stream);
int fgetpos(FILE *restrict stream, fpos_t *restrict pos);
int fsetpos(FILE *stream, const fpos_t *pos);
Expand Down
81 changes: 81 additions & 0 deletions clang/test/Analysis/stream-error.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,25 @@ void error_fseek(void) {
fclose(F);
}

void error_fseeko(void) {
FILE *F = fopen("file", "r");
if (!F)
return;
int rc = fseeko(F, 1, SEEK_SET);
if (rc) {
int IsFEof = feof(F), IsFError = ferror(F);
// Get feof or ferror or no error.
clang_analyzer_eval(IsFEof || IsFError);
// expected-warning@-1 {{FALSE}}
// expected-warning@-2 {{TRUE}}
clang_analyzer_eval(IsFEof && IsFError); // expected-warning {{FALSE}}
} else {
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
}
fclose(F);
}

void error_fseek_0(void) {
FILE *F = fopen("file", "r");
if (!F)
Expand Down Expand Up @@ -324,6 +343,68 @@ void error_fseek_0(void) {
fclose(F);
}

void error_fseeko_0(void) {
FILE *F = fopen("file", "r");
if (!F)
return;
int rc = fseeko(F, 0, SEEK_SET);
if (rc) {
int IsFEof = feof(F), IsFError = ferror(F);
// Get ferror or no error, but not feof.
clang_analyzer_eval(IsFError);
// expected-warning@-1 {{FALSE}}
// expected-warning@-2 {{TRUE}}
clang_analyzer_eval(IsFEof);
// expected-warning@-1 {{FALSE}}
} else {
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
}
fclose(F);
}

void error_ftell(void) {
FILE *F = fopen("file", "r");
if (!F)
return;
long rc = ftell(F);
if (rc >= 0)
clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
else
clang_analyzer_eval(rc == -1); // expected-warning {{TRUE}}
clang_analyzer_eval(feof(F) && ferror(F)); // expected-warning {{FALSE}}
StreamTesterChecker_make_feof_stream(F);
rc = ftell(F);
clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}}
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
StreamTesterChecker_make_ferror_stream(F);
rc = ftell(F);
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
fclose(F);
}

void error_ftello(void) {
FILE *F = fopen("file", "r");
if (!F)
return;
off_t rc = ftello(F);
if (rc >= 0)
clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
else
clang_analyzer_eval(rc == -1); // expected-warning {{TRUE}}
clang_analyzer_eval(feof(F) && ferror(F)); // expected-warning {{FALSE}}
StreamTesterChecker_make_feof_stream(F);
rc = ftello(F);
clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}}
clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
StreamTesterChecker_make_ferror_stream(F);
rc = ftello(F);
clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
fclose(F);
}

void error_fflush_after_fclose(void) {
FILE *F = tmpfile();
int Ret;
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/2006-05-19-SingleEltReturn.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct Y bar(void) {


// X86_32: define{{.*}} void @foo(ptr noundef %P)
// X86_32: call void @bar(ptr sret(%struct.Y) align 4 %{{[^),]*}})
// X86_32: call void @bar(ptr dead_on_unwind writable sret(%struct.Y) align 4 %{{[^),]*}})

// X86_32: define{{.*}} void @bar(ptr noalias sret(%struct.Y) align 4 %{{[^,)]*}})
// X86_32: define{{.*}} void @bar(ptr dead_on_unwind noalias writable sret(%struct.Y) align 4 %{{[^,)]*}})
// X86_32: ret void
22 changes: 11 additions & 11 deletions clang/test/CodeGen/64bit-swiftcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ SWIFTCALL int indirect_result_2(OUT int *arg0, OUT float *arg1) { __builtin_unr

typedef struct { char array[1024]; } struct_reallybig;
SWIFTCALL struct_reallybig indirect_result_3(OUT int *arg0, OUT float *arg1) { __builtin_unreachable(); }
// CHECK-LABEL: define {{.*}} void @indirect_result_3(ptr noalias sret(%struct.struct_reallybig) {{.*}}, ptr noalias align 4 dereferenceable(4){{.*}}, ptr noalias align 4 dereferenceable(4){{.*}})
// CHECK-LABEL: define {{.*}} void @indirect_result_3(ptr dead_on_unwind noalias writable sret(%struct.struct_reallybig) {{.*}}, ptr noalias align 4 dereferenceable(4){{.*}}, ptr noalias align 4 dereferenceable(4){{.*}})

SWIFTCALL void context_1(CONTEXT void *self) {}
// CHECK-LABEL: define {{.*}} void @context_1(ptr swiftself
Expand Down Expand Up @@ -238,7 +238,7 @@ typedef struct {
} struct_big_1;
TEST(struct_big_1)

// CHECK-LABEL: define {{.*}} void @return_struct_big_1({{.*}} noalias sret
// CHECK-LABEL: define {{.*}} void @return_struct_big_1(ptr dead_on_unwind noalias writable sret

// Should not be byval.
// CHECK-LABEL: define {{.*}} void @take_struct_big_1(ptr{{( %.*)?}})
Expand Down Expand Up @@ -522,7 +522,7 @@ typedef struct {
double d4;
} struct_d5;
TEST(struct_d5)
// CHECK: define{{.*}} swiftcc void @return_struct_d5(ptr noalias sret([[STRUCT5:.+]])
// CHECK: define{{.*}} swiftcc void @return_struct_d5(ptr dead_on_unwind noalias writable sret([[STRUCT5:.+]])
// CHECK: define{{.*}} swiftcc void @take_struct_d5(ptr

typedef struct {
Expand Down Expand Up @@ -709,7 +709,7 @@ typedef struct {
long long l4;
} struct_l5;
TEST(struct_l5)
// CHECK: define{{.*}} swiftcc void @return_struct_l5(ptr noalias sret([[STRUCT5:.+]])
// CHECK: define{{.*}} swiftcc void @return_struct_l5(ptr dead_on_unwind noalias writable sret([[STRUCT5:.+]])
// CHECK: define{{.*}} swiftcc void @take_struct_l5(ptr

typedef struct {
Expand Down Expand Up @@ -754,7 +754,7 @@ typedef struct {
char16 c4;
} struct_vc5;
TEST(struct_vc5)
// CHECK: define{{.*}} swiftcc void @return_struct_vc5(ptr noalias sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @return_struct_vc5(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @take_struct_vc5(ptr

typedef struct {
Expand Down Expand Up @@ -799,7 +799,7 @@ typedef struct {
short8 c4;
} struct_vs5;
TEST(struct_vs5)
// CHECK: define{{.*}} swiftcc void @return_struct_vs5(ptr noalias sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @return_struct_vs5(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @take_struct_vs5(ptr

typedef struct {
Expand Down Expand Up @@ -844,7 +844,7 @@ typedef struct {
int4 c4;
} struct_vi5;
TEST(struct_vi5)
// CHECK: define{{.*}} swiftcc void @return_struct_vi5(ptr noalias sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @return_struct_vi5(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @take_struct_vi5(ptr

typedef struct {
Expand Down Expand Up @@ -872,7 +872,7 @@ typedef struct {
long2 c4;
} struct_vl5;
TEST(struct_vl5)
// CHECK: define{{.*}} swiftcc void @return_struct_vl5(ptr noalias sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @return_struct_vl5(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @take_struct_vl5(ptr

typedef struct {
Expand Down Expand Up @@ -900,7 +900,7 @@ typedef struct {
double2 c4;
} struct_vd5;
TEST(struct_vd5)
// CHECK: define{{.*}} swiftcc void @return_struct_vd5(ptr noalias sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @return_struct_vd5(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @take_struct_vd5(ptr

typedef struct {
Expand All @@ -924,7 +924,7 @@ typedef struct {
double4 c2;
} struct_vd43;
TEST(struct_vd43)
// CHECK: define{{.*}} swiftcc void @return_struct_vd43(ptr noalias sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @return_struct_vd43(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @take_struct_vd43(ptr

typedef struct {
Expand Down Expand Up @@ -960,7 +960,7 @@ typedef struct {
float4 c4;
} struct_vf5;
TEST(struct_vf5)
// CHECK: define{{.*}} swiftcc void @return_struct_vf5(ptr noalias sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @return_struct_vf5(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]])
// CHECK: define{{.*}} swiftcc void @take_struct_vf5(ptr

typedef struct {
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/CSKY/csky-abi.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ void f_agg_large(struct large x) {

// The address where the struct should be written to will be the first
// argument
// CHECK-LABEL: define{{.*}} void @f_agg_large_ret(ptr noalias sret(%struct.large) align 4 %agg.result, i32 noundef %i, i8 noundef signext %j)
// CHECK-LABEL: define{{.*}} void @f_agg_large_ret(ptr dead_on_unwind noalias writable sret(%struct.large) align 4 %agg.result, i32 noundef %i, i8 noundef signext %j)
struct large f_agg_large_ret(int32_t i, int8_t j) {
return (struct large){1, 2, 3, 4};
}
Expand All @@ -144,7 +144,7 @@ int f_scalar_stack_1(struct tiny a, struct small b, struct small_aligned c,
// the presence of large return values that consume a register due to the need
// to pass a pointer.

// CHECK-LABEL: define{{.*}} void @f_scalar_stack_2(ptr noalias sret(%struct.large) align 4 %agg.result, i32 noundef %a, i64 noundef %b, i64 noundef %c, double noundef %d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef zeroext %g)
// CHECK-LABEL: define{{.*}} void @f_scalar_stack_2(ptr dead_on_unwind noalias writable sret(%struct.large) align 4 %agg.result, i32 noundef %a, i64 noundef %b, i64 noundef %c, double noundef %d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef zeroext %g)
struct large f_scalar_stack_2(int32_t a, int64_t b, int64_t c, long double d,
uint8_t e, int8_t f, uint8_t g) {
return (struct large){a, e, f, g};
Expand Down
44 changes: 22 additions & 22 deletions clang/test/CodeGen/CSKY/csky-hard-abi.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ struct double_float_s {
// CHECK: define{{.*}} void @f_double_double_s_arg([4 x i32] %a.coerce)
void f_double_double_s_arg(struct double_double_s a) {}

// CHECK: define{{.*}} void @f_ret_double_double_s(ptr noalias sret(%struct.double_double_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_double_s(ptr dead_on_unwind noalias writable sret(%struct.double_double_s) align 4 %agg.result)
struct double_double_s f_ret_double_double_s(void) {
return (struct double_double_s){1.0, 2.0};
}

// CHECK: define{{.*}} void @f_double_float_s_arg([3 x i32] %a.coerce)
void f_double_float_s_arg(struct double_float_s a) {}

// CHECK: define{{.*}} void @f_ret_double_float_s(ptr noalias sret(%struct.double_float_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_float_s(ptr dead_on_unwind noalias writable sret(%struct.double_float_s) align 4 %agg.result)
struct double_float_s f_ret_double_float_s(void) {
return (struct double_float_s){1.0, 2.0};
}
Expand Down Expand Up @@ -118,47 +118,47 @@ struct double_int8_zbf_s {
// CHECK: define{{.*}} @f_double_int8_s_arg([3 x i32] %a.coerce)
void f_double_int8_s_arg(struct double_int8_s a) {}

// CHECK: define{{.*}} void @f_ret_double_int8_s(ptr noalias sret(%struct.double_int8_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_int8_s(ptr dead_on_unwind noalias writable sret(%struct.double_int8_s) align 4 %agg.result)
struct double_int8_s f_ret_double_int8_s(void) {
return (struct double_int8_s){1.0, 2};
}

// CHECK: define{{.*}} void @f_double_uint8_s_arg([3 x i32] %a.coerce)
void f_double_uint8_s_arg(struct double_uint8_s a) {}

// CHECK: define{{.*}} void @f_ret_double_uint8_s(ptr noalias sret(%struct.double_uint8_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_uint8_s(ptr dead_on_unwind noalias writable sret(%struct.double_uint8_s) align 4 %agg.result)
struct double_uint8_s f_ret_double_uint8_s(void) {
return (struct double_uint8_s){1.0, 2};
}

// CHECK: define{{.*}} void @f_double_int32_s_arg([3 x i32] %a.coerce)
void f_double_int32_s_arg(struct double_int32_s a) {}

// CHECK: define{{.*}} void @f_ret_double_int32_s(ptr noalias sret(%struct.double_int32_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_int32_s(ptr dead_on_unwind noalias writable sret(%struct.double_int32_s) align 4 %agg.result)
struct double_int32_s f_ret_double_int32_s(void) {
return (struct double_int32_s){1.0, 2};
}

// CHECK: define{{.*}} void @f_double_int64_s_arg([4 x i32] %a.coerce)
void f_double_int64_s_arg(struct double_int64_s a) {}

// CHECK: define{{.*}} void @f_ret_double_int64_s(ptr noalias sret(%struct.double_int64_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_int64_s(ptr dead_on_unwind noalias writable sret(%struct.double_int64_s) align 4 %agg.result)
struct double_int64_s f_ret_double_int64_s(void) {
return (struct double_int64_s){1.0, 2};
}

// CHECK: define{{.*}} void @f_double_int64bf_s_arg([3 x i32] %a.coerce)
void f_double_int64bf_s_arg(struct double_int64bf_s a) {}

// CHECK: define{{.*}} void @f_ret_double_int64bf_s(ptr noalias sret(%struct.double_int64bf_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_int64bf_s(ptr dead_on_unwind noalias writable sret(%struct.double_int64bf_s) align 4 %agg.result)
struct double_int64bf_s f_ret_double_int64bf_s(void) {
return (struct double_int64bf_s){1.0, 2};
}

// CHECK: define{{.*}} void @f_double_int8_zbf_s([3 x i32] %a.coerce)
void f_double_int8_zbf_s(struct double_int8_zbf_s a) {}

// CHECK: define{{.*}} void @f_ret_double_int8_zbf_s(ptr noalias sret(%struct.double_int8_zbf_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_int8_zbf_s(ptr dead_on_unwind noalias writable sret(%struct.double_int8_zbf_s) align 4 %agg.result)
struct double_int8_zbf_s f_ret_double_int8_zbf_s(void) {
return (struct double_int8_zbf_s){1.0, 2};
}
Expand All @@ -179,7 +179,7 @@ void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double
// CHECK: define{{.*}} void @f_doublecomplex(double noundef %a.coerce0, double noundef %a.coerce1)
void f_doublecomplex(double __complex__ a) {}

// CHECK: define{{.*}} void @f_ret_doublecomplex(ptr noalias sret({ double, double }) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublecomplex(ptr dead_on_unwind noalias writable sret({ double, double }) align 4 %agg.result)
double __complex__ f_ret_doublecomplex(void) {
return 1.0;
}
Expand All @@ -191,7 +191,7 @@ struct doublecomplex_s {
// CHECK: define{{.*}} void @f_doublecomplex_s_arg([4 x i32] %a.coerce)
void f_doublecomplex_s_arg(struct doublecomplex_s a) {}

// CHECK: define{{.*}} void @f_ret_doublecomplex_s(ptr noalias sret(%struct.doublecomplex_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublecomplex_s(ptr dead_on_unwind noalias writable sret(%struct.doublecomplex_s) align 4 %agg.result)
struct doublecomplex_s f_ret_doublecomplex_s(void) {
return (struct doublecomplex_s){1.0};
}
Expand All @@ -218,7 +218,7 @@ struct doublearr2_s {
// CHECK: define{{.*}} void @f_doublearr2_s_arg([4 x i32] %a.coerce)
void f_doublearr2_s_arg(struct doublearr2_s a) {}

// CHECK: define{{.*}} void @f_ret_doublearr2_s(ptr noalias sret(%struct.doublearr2_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublearr2_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_s) align 4 %agg.result)
struct doublearr2_s f_ret_doublearr2_s(void) {
return (struct doublearr2_s){{1.0, 2.0}};
}
Expand All @@ -232,7 +232,7 @@ struct doublearr2_tricky1_s {
// CHECK: define{{.*}} void @f_doublearr2_tricky1_s_arg([4 x i32] %a.coerce)
void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a) {}

// CHECK: define{{.*}} void @f_ret_doublearr2_tricky1_s(ptr noalias sret(%struct.doublearr2_tricky1_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublearr2_tricky1_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky1_s) align 4 %agg.result)
struct doublearr2_tricky1_s f_ret_doublearr2_tricky1_s(void) {
return (struct doublearr2_tricky1_s){{{{1.0}}, {{2.0}}}};
}
Expand All @@ -247,7 +247,7 @@ struct doublearr2_tricky2_s {
// CHECK: define{{.*}} void @f_doublearr2_tricky2_s_arg([4 x i32] %a.coerce)
void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a) {}

// CHECK: define{{.*}} void @f_ret_doublearr2_tricky2_s(ptr noalias sret(%struct.doublearr2_tricky2_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublearr2_tricky2_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky2_s) align 4 %agg.result)
struct doublearr2_tricky2_s f_ret_doublearr2_tricky2_s(void) {
return (struct doublearr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};
}
Expand All @@ -262,7 +262,7 @@ struct doublearr2_tricky3_s {
// CHECK: define{{.*}} void @f_doublearr2_tricky3_s_arg([4 x i32] %a.coerce)
void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a) {}

// CHECK: define{{.*}} void @f_ret_doublearr2_tricky3_s(ptr noalias sret(%struct.doublearr2_tricky3_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublearr2_tricky3_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky3_s) align 4 %agg.result)
struct doublearr2_tricky3_s f_ret_doublearr2_tricky3_s(void) {
return (struct doublearr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};
}
Expand All @@ -278,7 +278,7 @@ struct doublearr2_tricky4_s {
// CHECK: define{{.*}} void @f_doublearr2_tricky4_s_arg([4 x i32] %a.coerce)
void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a) {}

// CHECK: define{{.*}} void @f_ret_doublearr2_tricky4_s(ptr noalias sret(%struct.doublearr2_tricky4_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublearr2_tricky4_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky4_s) align 4 %agg.result)
struct doublearr2_tricky4_s f_ret_doublearr2_tricky4_s(void) {
return (struct doublearr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}};
}
Expand All @@ -292,7 +292,7 @@ struct int_double_int_s {
// CHECK: define{{.*}} void @f_int_double_int_s_arg([4 x i32] %a.coerce)
void f_int_double_int_s_arg(struct int_double_int_s a) {}

// CHECK: define{{.*}} void @f_ret_int_double_int_s(ptr noalias sret(%struct.int_double_int_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_int_double_int_s(ptr dead_on_unwind noalias writable sret(%struct.int_double_int_s) align 4 %agg.result)
struct int_double_int_s f_ret_int_double_int_s(void) {
return (struct int_double_int_s){1, 2.0, 3};
}
Expand All @@ -305,7 +305,7 @@ struct int64_double_s {
// CHECK: define{{.*}} void @f_int64_double_s_arg([4 x i32] %a.coerce)
void f_int64_double_s_arg(struct int64_double_s a) {}

// CHECK: define{{.*}} void @f_ret_int64_double_s(ptr noalias sret(%struct.int64_double_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_int64_double_s(ptr dead_on_unwind noalias writable sret(%struct.int64_double_s) align 4 %agg.result)
struct int64_double_s f_ret_int64_double_s(void) {
return (struct int64_double_s){1, 2.0};
}
Expand All @@ -319,7 +319,7 @@ struct char_char_double_s {
// CHECK-LABEL: define{{.*}} void @f_char_char_double_s_arg([3 x i32] %a.coerce)
void f_char_char_double_s_arg(struct char_char_double_s a) {}

// CHECK: define{{.*}} void @f_ret_char_char_double_s(ptr noalias sret(%struct.char_char_double_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_char_char_double_s(ptr dead_on_unwind noalias writable sret(%struct.char_char_double_s) align 4 %agg.result)
struct char_char_double_s f_ret_char_char_double_s(void) {
return (struct char_char_double_s){1, 2, 3.0};
}
Expand All @@ -338,19 +338,19 @@ union double_u f_ret_double_u(void) {
return (union double_u){1.0};
}

// CHECK: define{{.*}} void @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(ptr noalias sret(%struct.double_int32_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce)
// CHECK: define{{.*}} void @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(ptr dead_on_unwind noalias writable sret(%struct.double_int32_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce)
struct double_int32_s f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(
int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
return (struct double_int32_s){1.0, 2};
}

// CHECK: define{{.*}} void @f_ret_double_double_s_double_int32_s_just_sufficient_gprs(ptr noalias sret(%struct.double_double_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce)
// CHECK: define{{.*}} void @f_ret_double_double_s_double_int32_s_just_sufficient_gprs(ptr dead_on_unwind noalias writable sret(%struct.double_double_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce)
struct double_double_s f_ret_double_double_s_double_int32_s_just_sufficient_gprs(
int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
return (struct double_double_s){1.0, 2.0};
}

// CHECK: define{{.*}} void @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(ptr noalias sret({ double, double }) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce)
// CHECK: define{{.*}} void @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(ptr dead_on_unwind noalias writable sret({ double, double }) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce)
double __complex__ f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(
int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
return 1.0;
Expand All @@ -376,7 +376,7 @@ struct large {
// the presence of large return values that consume a register due to the need
// to pass a pointer.

// CHECK-LABEL: define{{.*}} void @f_scalar_stack_2(ptr noalias sret(%struct.large) align 4 %agg.result, float noundef %a, i64 noundef %b, double noundef %c, double noundef %d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef zeroext %g)
// CHECK-LABEL: define{{.*}} void @f_scalar_stack_2(ptr dead_on_unwind noalias writable sret(%struct.large) align 4 %agg.result, float noundef %a, i64 noundef %b, double noundef %c, double noundef %d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef zeroext %g)
struct large f_scalar_stack_2(float a, int64_t b, double c, long double d,
uint8_t e, int8_t f, uint8_t g) {
return (struct large){a, e, f, g};
Expand Down
44 changes: 22 additions & 22 deletions clang/test/CodeGen/CSKY/csky-soft-abi.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ struct double_float_s {
// CHECK: define{{.*}} void @f_double_double_s_arg([4 x i32] %a.coerce)
void f_double_double_s_arg(struct double_double_s a) {}

// CHECK: define{{.*}} void @f_ret_double_double_s(ptr noalias sret(%struct.double_double_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_double_s(ptr dead_on_unwind noalias writable sret(%struct.double_double_s) align 4 %agg.result)
struct double_double_s f_ret_double_double_s(void) {
return (struct double_double_s){1.0, 2.0};
}

// CHECK: define{{.*}} void @f_double_float_s_arg([3 x i32] %a.coerce)
void f_double_float_s_arg(struct double_float_s a) {}

// CHECK: define{{.*}} void @f_ret_double_float_s(ptr noalias sret(%struct.double_float_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_float_s(ptr dead_on_unwind noalias writable sret(%struct.double_float_s) align 4 %agg.result)
struct double_float_s f_ret_double_float_s(void) {
return (struct double_float_s){1.0, 2.0};
}
Expand Down Expand Up @@ -118,47 +118,47 @@ struct double_int8_zbf_s {
// CHECK: define{{.*}} @f_double_int8_s_arg([3 x i32] %a.coerce)
void f_double_int8_s_arg(struct double_int8_s a) {}

// CHECK: define{{.*}} void @f_ret_double_int8_s(ptr noalias sret(%struct.double_int8_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_int8_s(ptr dead_on_unwind noalias writable sret(%struct.double_int8_s) align 4 %agg.result)
struct double_int8_s f_ret_double_int8_s(void) {
return (struct double_int8_s){1.0, 2};
}

// CHECK: define{{.*}} void @f_double_uint8_s_arg([3 x i32] %a.coerce)
void f_double_uint8_s_arg(struct double_uint8_s a) {}

// CHECK: define{{.*}} void @f_ret_double_uint8_s(ptr noalias sret(%struct.double_uint8_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_uint8_s(ptr dead_on_unwind noalias writable sret(%struct.double_uint8_s) align 4 %agg.result)
struct double_uint8_s f_ret_double_uint8_s(void) {
return (struct double_uint8_s){1.0, 2};
}

// CHECK: define{{.*}} void @f_double_int32_s_arg([3 x i32] %a.coerce)
void f_double_int32_s_arg(struct double_int32_s a) {}

// CHECK: define{{.*}} void @f_ret_double_int32_s(ptr noalias sret(%struct.double_int32_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_int32_s(ptr dead_on_unwind noalias writable sret(%struct.double_int32_s) align 4 %agg.result)
struct double_int32_s f_ret_double_int32_s(void) {
return (struct double_int32_s){1.0, 2};
}

// CHECK: define{{.*}} void @f_double_int64_s_arg([4 x i32] %a.coerce)
void f_double_int64_s_arg(struct double_int64_s a) {}

// CHECK: define{{.*}} void @f_ret_double_int64_s(ptr noalias sret(%struct.double_int64_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_int64_s(ptr dead_on_unwind noalias writable sret(%struct.double_int64_s) align 4 %agg.result)
struct double_int64_s f_ret_double_int64_s(void) {
return (struct double_int64_s){1.0, 2};
}

// CHECK: define{{.*}} void @f_double_int64bf_s_arg([3 x i32] %a.coerce)
void f_double_int64bf_s_arg(struct double_int64bf_s a) {}

// CHECK: define{{.*}} void @f_ret_double_int64bf_s(ptr noalias sret(%struct.double_int64bf_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_int64bf_s(ptr dead_on_unwind noalias writable sret(%struct.double_int64bf_s) align 4 %agg.result)
struct double_int64bf_s f_ret_double_int64bf_s(void) {
return (struct double_int64bf_s){1.0, 2};
}

// CHECK: define{{.*}} void @f_double_int8_zbf_s([3 x i32] %a.coerce)
void f_double_int8_zbf_s(struct double_int8_zbf_s a) {}

// CHECK: define{{.*}} void @f_ret_double_int8_zbf_s(ptr noalias sret(%struct.double_int8_zbf_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_double_int8_zbf_s(ptr dead_on_unwind noalias writable sret(%struct.double_int8_zbf_s) align 4 %agg.result)
struct double_int8_zbf_s f_ret_double_int8_zbf_s(void) {
return (struct double_int8_zbf_s){1.0, 2};
}
Expand All @@ -180,7 +180,7 @@ void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double
// CHECK: define{{.*}} void @f_doublecomplex([4 x i32] noundef %a.coerce)
void f_doublecomplex(double __complex__ a) {}

// CHECK: define{{.*}} void @f_ret_doublecomplex(ptr noalias sret({ double, double }) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublecomplex(ptr dead_on_unwind noalias writable sret({ double, double }) align 4 %agg.result)
double __complex__ f_ret_doublecomplex(void) {
return 1.0;
}
Expand All @@ -192,7 +192,7 @@ struct doublecomplex_s {
// CHECK: define{{.*}} void @f_doublecomplex_s_arg([4 x i32] %a.coerce)
void f_doublecomplex_s_arg(struct doublecomplex_s a) {}

// CHECK: define{{.*}} void @f_ret_doublecomplex_s(ptr noalias sret(%struct.doublecomplex_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublecomplex_s(ptr dead_on_unwind noalias writable sret(%struct.doublecomplex_s) align 4 %agg.result)
struct doublecomplex_s f_ret_doublecomplex_s(void) {
return (struct doublecomplex_s){1.0};
}
Expand All @@ -219,7 +219,7 @@ struct doublearr2_s {
// CHECK: define{{.*}} void @f_doublearr2_s_arg([4 x i32] %a.coerce)
void f_doublearr2_s_arg(struct doublearr2_s a) {}

// CHECK: define{{.*}} void @f_ret_doublearr2_s(ptr noalias sret(%struct.doublearr2_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublearr2_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_s) align 4 %agg.result)
struct doublearr2_s f_ret_doublearr2_s(void) {
return (struct doublearr2_s){{1.0, 2.0}};
}
Expand All @@ -233,7 +233,7 @@ struct doublearr2_tricky1_s {
// CHECK: define{{.*}} void @f_doublearr2_tricky1_s_arg([4 x i32] %a.coerce)
void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a) {}

// CHECK: define{{.*}} void @f_ret_doublearr2_tricky1_s(ptr noalias sret(%struct.doublearr2_tricky1_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublearr2_tricky1_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky1_s) align 4 %agg.result)
struct doublearr2_tricky1_s f_ret_doublearr2_tricky1_s(void) {
return (struct doublearr2_tricky1_s){{{{1.0}}, {{2.0}}}};
}
Expand All @@ -248,7 +248,7 @@ struct doublearr2_tricky2_s {
// CHECK: define{{.*}} void @f_doublearr2_tricky2_s_arg([4 x i32] %a.coerce)
void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a) {}

// CHECK: define{{.*}} void @f_ret_doublearr2_tricky2_s(ptr noalias sret(%struct.doublearr2_tricky2_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublearr2_tricky2_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky2_s) align 4 %agg.result)
struct doublearr2_tricky2_s f_ret_doublearr2_tricky2_s(void) {
return (struct doublearr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}};
}
Expand All @@ -263,7 +263,7 @@ struct doublearr2_tricky3_s {
// CHECK: define{{.*}} void @f_doublearr2_tricky3_s_arg([4 x i32] %a.coerce)
void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a) {}

// CHECK: define{{.*}} void @f_ret_doublearr2_tricky3_s(ptr noalias sret(%struct.doublearr2_tricky3_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublearr2_tricky3_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky3_s) align 4 %agg.result)
struct doublearr2_tricky3_s f_ret_doublearr2_tricky3_s(void) {
return (struct doublearr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}};
}
Expand All @@ -279,7 +279,7 @@ struct doublearr2_tricky4_s {
// CHECK: define{{.*}} void @f_doublearr2_tricky4_s_arg([4 x i32] %a.coerce)
void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a) {}

// CHECK: define{{.*}} void @f_ret_doublearr2_tricky4_s(ptr noalias sret(%struct.doublearr2_tricky4_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_doublearr2_tricky4_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky4_s) align 4 %agg.result)
struct doublearr2_tricky4_s f_ret_doublearr2_tricky4_s(void) {
return (struct doublearr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}};
}
Expand All @@ -293,7 +293,7 @@ struct int_double_int_s {
// CHECK: define{{.*}} void @f_int_double_int_s_arg([4 x i32] %a.coerce)
void f_int_double_int_s_arg(struct int_double_int_s a) {}

// CHECK: define{{.*}} void @f_ret_int_double_int_s(ptr noalias sret(%struct.int_double_int_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_int_double_int_s(ptr dead_on_unwind noalias writable sret(%struct.int_double_int_s) align 4 %agg.result)
struct int_double_int_s f_ret_int_double_int_s(void) {
return (struct int_double_int_s){1, 2.0, 3};
}
Expand All @@ -306,7 +306,7 @@ struct int64_double_s {
// CHECK: define{{.*}} void @f_int64_double_s_arg([4 x i32] %a.coerce)
void f_int64_double_s_arg(struct int64_double_s a) {}

// CHECK: define{{.*}} void @f_ret_int64_double_s(ptr noalias sret(%struct.int64_double_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_int64_double_s(ptr dead_on_unwind noalias writable sret(%struct.int64_double_s) align 4 %agg.result)
struct int64_double_s f_ret_int64_double_s(void) {
return (struct int64_double_s){1, 2.0};
}
Expand All @@ -320,7 +320,7 @@ struct char_char_double_s {
// CHECK-LABEL: define{{.*}} void @f_char_char_double_s_arg([3 x i32] %a.coerce)
void f_char_char_double_s_arg(struct char_char_double_s a) {}

// CHECK: define{{.*}} void @f_ret_char_char_double_s(ptr noalias sret(%struct.char_char_double_s) align 4 %agg.result)
// CHECK: define{{.*}} void @f_ret_char_char_double_s(ptr dead_on_unwind noalias writable sret(%struct.char_char_double_s) align 4 %agg.result)
struct char_char_double_s f_ret_char_char_double_s(void) {
return (struct char_char_double_s){1, 2, 3.0};
}
Expand All @@ -339,19 +339,19 @@ union double_u f_ret_double_u(void) {
return (union double_u){1.0};
}

// CHECK: define{{.*}} void @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(ptr noalias sret(%struct.double_int32_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce)
// CHECK: define{{.*}} void @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(ptr dead_on_unwind noalias writable sret(%struct.double_int32_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce)
struct double_int32_s f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(
int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
return (struct double_int32_s){1.0, 2};
}

// CHECK: define{{.*}} void @f_ret_double_double_s_double_int32_s_just_sufficient_gprs(ptr noalias sret(%struct.double_double_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce)
// CHECK: define{{.*}} void @f_ret_double_double_s_double_int32_s_just_sufficient_gprs(ptr dead_on_unwind noalias writable sret(%struct.double_double_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce)
struct double_double_s f_ret_double_double_s_double_int32_s_just_sufficient_gprs(
int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
return (struct double_double_s){1.0, 2.0};
}

// CHECK: define{{.*}} void @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(ptr noalias sret({ double, double }) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce)
// CHECK: define{{.*}} void @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(ptr dead_on_unwind noalias writable sret({ double, double }) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce)
double __complex__ f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(
int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) {
return 1.0;
Expand All @@ -377,7 +377,7 @@ struct large {
// the presence of large return values that consume a register due to the need
// to pass a pointer.

// CHECK-LABEL: define{{.*}} void @f_scalar_stack_2(ptr noalias sret(%struct.large) align 4 %agg.result, float noundef %a, i64 noundef %b, double noundef %c, double noundef %d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef zeroext %g)
// CHECK-LABEL: define{{.*}} void @f_scalar_stack_2(ptr dead_on_unwind noalias writable sret(%struct.large) align 4 %agg.result, float noundef %a, i64 noundef %b, double noundef %c, double noundef %d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef zeroext %g)
struct large f_scalar_stack_2(float a, int64_t b, double c, long double d,
uint8_t e, int8_t f, uint8_t g) {
return (struct large){a, e, f, g};
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/PowerPC/aix-alignment.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ StructDouble d1;
// AIX: ret double %0
double retDouble(double x) { return x; }

// AIX32: define void @bar(ptr noalias sret(%struct.StructDouble) align 4 %agg.result, ptr noundef byval(%struct.StructDouble) align 4 %x)
// AIX64: define void @bar(ptr noalias sret(%struct.StructDouble) align 4 %agg.result, ptr noundef byval(%struct.StructDouble) align 8 %x)
// AIX32: define void @bar(ptr dead_on_unwind noalias writable sret(%struct.StructDouble) align 4 %agg.result, ptr noundef byval(%struct.StructDouble) align 4 %x)
// AIX64: define void @bar(ptr dead_on_unwind noalias writable sret(%struct.StructDouble) align 4 %agg.result, ptr noundef byval(%struct.StructDouble) align 8 %x)
// AIX32: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %agg.result, ptr align 4 %x, i32 16, i1 false)
// AIX64: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.result, ptr align 8 %x, i64 16, i1 false)
StructDouble bar(StructDouble x) { return x; }
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CodeGen/PowerPC/powerpc-c99complex.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ _Complex float foo1(_Complex float x) {
// CHECK-LABEL: define{{.*}} { float, float } @foo1(float noundef %x.{{.*}}, float noundef %x.{{.*}}) #0 {
// CHECK: ret { float, float }

// PPC32LNX-LABEL: define{{.*}} void @foo1(ptr noalias sret({ float, float }) align 4 %agg.result, ptr noundef byval({ float, float }) align 4 %x) #0 {
// PPC32LNX-LABEL: define{{.*}} void @foo1(ptr dead_on_unwind noalias writable sret({ float, float }) align 4 %agg.result, ptr noundef byval({ float, float }) align 4 %x) #0 {
// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { float, float }, ptr %agg.result, i32 0, i32 0
// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { float, float }, ptr %agg.result, i32 0, i32 1
// PPC32LNX-NEXT: store float %{{.*}}, ptr [[RETREAL]], align 4
Expand All @@ -21,7 +21,7 @@ _Complex double foo2(_Complex double x) {
// CHECK-LABEL: define{{.*}} { double, double } @foo2(double noundef %x.{{.*}}, double noundef %x.{{.*}}) #0 {
// CHECK: ret { double, double }

// PPC32LNX-LABEL: define{{.*}} void @foo2(ptr noalias sret({ double, double }) align 8 %agg.result, ptr noundef byval({ double, double }) align 8 %x) #0 {
// PPC32LNX-LABEL: define{{.*}} void @foo2(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %agg.result, ptr noundef byval({ double, double }) align 8 %x) #0 {
// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { double, double }, ptr %agg.result, i32 0, i32 0
// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { double, double }, ptr %agg.result, i32 0, i32 1
// PPC32LNX-NEXT: store double %{{.*}}, ptr [[RETREAL]], align 8
Expand All @@ -36,7 +36,7 @@ _Complex long double foo3(_Complex long double x) {
// CHECK-LDBL128-LABEL: define{{.*}} { ppc_fp128, ppc_fp128 } @foo3(ppc_fp128 noundef %x.{{.*}}, ppc_fp128 noundef %x.{{.*}}) #0 {
// CHECK-LDBL128: ret { ppc_fp128, ppc_fp128 }

// PPC32LNX-LABEL: define{{.*}} void @foo3(ptr noalias sret({ ppc_fp128, ppc_fp128 }) align 16 %agg.result, ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 %x) #0 {
// PPC32LNX-LABEL: define{{.*}} void @foo3(ptr dead_on_unwind noalias writable sret({ ppc_fp128, ppc_fp128 }) align 16 %agg.result, ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 %x) #0 {
// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 0
// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 1
// PPC32LNX-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETREAL]], align 16
Expand Down
22 changes: 11 additions & 11 deletions clang/test/CodeGen/PowerPC/ppc-aggregate-abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,57 @@
// RUN: -o - %s | FileCheck %s -check-prefix=CHECK-LE

class agg_float_class { float a; };
// CHECK-BE-LABEL: define{{.*}} void @_Z20pass_agg_float_class15agg_float_class(ptr noalias sret(%class.agg_float_class) align 4 %{{.*}}, float inreg %{{.*}})
// CHECK-BE-LABEL: define{{.*}} void @_Z20pass_agg_float_class15agg_float_class(ptr dead_on_unwind noalias writable sret(%class.agg_float_class) align 4 %{{.*}}, float inreg %{{.*}})
// CHECK-LE-LABEL: define{{.*}} [1 x float] @_Z20pass_agg_float_class15agg_float_class(float inreg %{{.*}})
agg_float_class pass_agg_float_class(agg_float_class arg) { return arg; }

class agg_double_class { double a; };
// CHECK-BE-LABEL: define{{.*}} void @_Z21pass_agg_double_class16agg_double_class(ptr noalias sret(%class.agg_double_class) align 8 %{{.*}}, double inreg %{{.*}})
// CHECK-BE-LABEL: define{{.*}} void @_Z21pass_agg_double_class16agg_double_class(ptr dead_on_unwind noalias writable sret(%class.agg_double_class) align 8 %{{.*}}, double inreg %{{.*}})
// CHECK-LE-LABEL: define{{.*}} [1 x double] @_Z21pass_agg_double_class16agg_double_class(double inreg %{{.*}})
agg_double_class pass_agg_double_class(agg_double_class arg) { return arg; }

struct agg_float_cpp { float a; int : 0; };
// CHECK-BE-LABEL: define{{.*}} void @_Z18pass_agg_float_cpp13agg_float_cpp(ptr noalias sret(%struct.agg_float_cpp) align 4 %{{.*}}, float inreg %{{.*}})
// CHECK-BE-LABEL: define{{.*}} void @_Z18pass_agg_float_cpp13agg_float_cpp(ptr dead_on_unwind noalias writable sret(%struct.agg_float_cpp) align 4 %{{.*}}, float inreg %{{.*}})
// CHECK-LE-LABEL: define{{.*}} [1 x float] @_Z18pass_agg_float_cpp13agg_float_cpp(float inreg %{{.*}})
agg_float_cpp pass_agg_float_cpp(agg_float_cpp arg) { return arg; }

struct empty { };
struct agg_nofloat_empty { float a; empty dummy; };
// CHECK-BE-LABEL: define{{.*}} void @_Z22pass_agg_nofloat_empty17agg_nofloat_empty(ptr noalias sret(%struct.agg_nofloat_empty) align 4 %{{.*}}, i64 %{{.*}})
// CHECK-BE-LABEL: define{{.*}} void @_Z22pass_agg_nofloat_empty17agg_nofloat_empty(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_empty) align 4 %{{.*}}, i64 %{{.*}})
// CHECK-LE-LABEL: define{{.*}} i64 @_Z22pass_agg_nofloat_empty17agg_nofloat_empty(i64 %{{.*}})
agg_nofloat_empty pass_agg_nofloat_empty(agg_nofloat_empty arg) { return arg; }

struct agg_float_empty { float a; [[no_unique_address]] empty dummy; };
// CHECK-BE-LABEL: define{{.*}} void @_Z20pass_agg_float_empty15agg_float_empty(ptr noalias sret(%struct.agg_float_empty) align 4 %{{.*}}, float inreg %{{.*}})
// CHECK-BE-LABEL: define{{.*}} void @_Z20pass_agg_float_empty15agg_float_empty(ptr dead_on_unwind noalias writable sret(%struct.agg_float_empty) align 4 %{{.*}}, float inreg %{{.*}})
// CHECK-LE-LABEL: define{{.*}} [1 x float] @_Z20pass_agg_float_empty15agg_float_empty(float inreg %{{.*}})
agg_float_empty pass_agg_float_empty(agg_float_empty arg) { return arg; }

struct agg_nofloat_emptyarray { float a; [[no_unique_address]] empty dummy[3]; };
// CHECK-BE-LABEL: define{{.*}} void @_Z27pass_agg_nofloat_emptyarray22agg_nofloat_emptyarray(ptr noalias sret(%struct.agg_nofloat_emptyarray) align 4 %{{.*}}, i64 %{{.*}})
// CHECK-BE-LABEL: define{{.*}} void @_Z27pass_agg_nofloat_emptyarray22agg_nofloat_emptyarray(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_emptyarray) align 4 %{{.*}}, i64 %{{.*}})
// CHECK-LE-LABEL: define{{.*}} i64 @_Z27pass_agg_nofloat_emptyarray22agg_nofloat_emptyarray(i64 %{{.*}})
agg_nofloat_emptyarray pass_agg_nofloat_emptyarray(agg_nofloat_emptyarray arg) { return arg; }

struct noemptybase { empty dummy; };
struct agg_nofloat_emptybase : noemptybase { float a; };
// CHECK-BE-LABEL: define{{.*}} void @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(ptr noalias sret(%struct.agg_nofloat_emptybase) align 4 %{{.*}}, i64 %{{.*}})
// CHECK-BE-LABEL: define{{.*}} void @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_emptybase) align 4 %{{.*}}, i64 %{{.*}})
// CHECK-LE-LABEL: define{{.*}} i64 @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(i64 %{{.*}})
agg_nofloat_emptybase pass_agg_nofloat_emptybase(agg_nofloat_emptybase arg) { return arg; }

struct emptybase { [[no_unique_address]] empty dummy; };
struct agg_float_emptybase : emptybase { float a; };
// CHECK-BE-LABEL: define{{.*}} void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr noalias sret(%struct.agg_float_emptybase) align 4 %{{.*}}, float inreg %{{.*}})
// CHECK-BE-LABEL: define{{.*}} void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr dead_on_unwind noalias writable sret(%struct.agg_float_emptybase) align 4 %{{.*}}, float inreg %{{.*}})
// CHECK-LE-LABEL: define{{.*}} [1 x float] @_Z24pass_agg_float_emptybase19agg_float_emptybase(float inreg %{{.*}})
agg_float_emptybase pass_agg_float_emptybase(agg_float_emptybase arg) { return arg; }

struct noemptybasearray { [[no_unique_address]] empty dummy[3]; };
struct agg_nofloat_emptybasearray : noemptybasearray { float a; };
// CHECK-BE-LABEL: define{{.*}} void @_Z31pass_agg_nofloat_emptybasearray26agg_nofloat_emptybasearray(ptr noalias sret(%struct.agg_nofloat_emptybasearray) align 4 %{{.*}}, i64 %{{.*}})
// CHECK-BE-LABEL: define{{.*}} void @_Z31pass_agg_nofloat_emptybasearray26agg_nofloat_emptybasearray(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_emptybasearray) align 4 %{{.*}}, i64 %{{.*}})
// CHECK-LE-LABEL: define{{.*}} i64 @_Z31pass_agg_nofloat_emptybasearray26agg_nofloat_emptybasearray(i64 %{{.*}})
agg_nofloat_emptybasearray pass_agg_nofloat_emptybasearray(agg_nofloat_emptybasearray arg) { return arg; }

// CHECK-BE: call void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr sret(%struct.agg_float_emptybase) align 4 %{{.*}}, float inreg %{{.*}})
// CHECK-BE: call void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr dead_on_unwind writable sret(%struct.agg_float_emptybase) align 4 %{{.*}}, float inreg %{{.*}})
// CHECK-LE: call [1 x float] @_Z24pass_agg_float_emptybase19agg_float_emptybase(float inreg %{{.*}})
void pass_agg_float_emptybase_ptr(agg_float_emptybase* arg) { pass_agg_float_emptybase(*arg); }
// CHECK-BE: call void @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(ptr sret(%struct.agg_nofloat_emptybase) align 4 %{{.*}}, i64 %{{.*}})
// CHECK-BE: call void @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(ptr dead_on_unwind writable sret(%struct.agg_nofloat_emptybase) align 4 %{{.*}}, i64 %{{.*}})
// CHECK-LE: call i64 @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(i64 %{{.*}})
void pass_agg_nofloat_emptybase_ptr(agg_nofloat_emptybase* arg) { pass_agg_nofloat_emptybase(*arg); }
22 changes: 11 additions & 11 deletions clang/test/CodeGen/PowerPC/ppc32-and-aix-struct-return.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,42 +59,42 @@ typedef struct {
char c[9];
} Nine;

// CHECK-AIX-LABEL: define{{.*}} void @ret0(ptr noalias sret(%struct.Zero) {{[^,]*}})
// CHECK-AIX-LABEL: define{{.*}} void @ret0(ptr dead_on_unwind noalias writable sret(%struct.Zero) {{[^,]*}})
// CHECK-SVR4-LABEL: define{{.*}} void @ret0()
Zero ret0(void) { return (Zero){}; }

// CHECK-AIX-LABEL: define{{.*}} void @ret1(ptr noalias sret(%struct.One) {{[^,]*}})
// CHECK-AIX-LABEL: define{{.*}} void @ret1(ptr dead_on_unwind noalias writable sret(%struct.One) {{[^,]*}})
// CHECK-SVR4-LABEL: define{{.*}} i8 @ret1()
One ret1(void) { return (One){'a'}; }

// CHECK-AIX-LABEL: define{{.*}} void @ret2(ptr noalias sret(%struct.Two) {{[^,]*}})
// CHECK-AIX-LABEL: define{{.*}} void @ret2(ptr dead_on_unwind noalias writable sret(%struct.Two) {{[^,]*}})
// CHECK-SVR4-LABEL: define{{.*}} i16 @ret2()
Two ret2(void) { return (Two){123}; }

// CHECK-AIX-LABEL: define{{.*}} void @ret3(ptr noalias sret(%struct.Three) {{[^,]*}})
// CHECK-AIX-LABEL: define{{.*}} void @ret3(ptr dead_on_unwind noalias writable sret(%struct.Three) {{[^,]*}})
// CHECK-SVR4-LABEL: define{{.*}} i24 @ret3()
Three ret3(void) { return (Three){"abc"}; }

// CHECK-AIX-LABEL: define{{.*}} void @ret4(ptr noalias sret(%struct.Four) {{[^,]*}})
// CHECK-AIX-LABEL: define{{.*}} void @ret4(ptr dead_on_unwind noalias writable sret(%struct.Four) {{[^,]*}})
// CHECK-SVR4-LABEL: define{{.*}} i32 @ret4()
Four ret4(void) { return (Four){0.4}; }

// CHECK-AIX-LABEL: define{{.*}} void @ret5(ptr noalias sret(%struct.Five) {{[^,]*}})
// CHECK-AIX-LABEL: define{{.*}} void @ret5(ptr dead_on_unwind noalias writable sret(%struct.Five) {{[^,]*}})
// CHECK-SVR4-LABEL: define{{.*}} i40 @ret5()
Five ret5(void) { return (Five){"abcde"}; }

// CHECK-AIX-LABEL: define{{.*}} void @ret6(ptr noalias sret(%struct.Six) {{[^,]*}})
// CHECK-AIX-LABEL: define{{.*}} void @ret6(ptr dead_on_unwind noalias writable sret(%struct.Six) {{[^,]*}})
// CHECK-SVR4-LABEL: define{{.*}} i48 @ret6()
Six ret6(void) { return (Six){12, 34, 56}; }

// CHECK-AIX-LABEL: define{{.*}} void @ret7(ptr noalias sret(%struct.Seven) {{[^,]*}})
// CHECK-AIX-LABEL: define{{.*}} void @ret7(ptr dead_on_unwind noalias writable sret(%struct.Seven) {{[^,]*}})
// CHECK-SVR4-LABEL: define{{.*}} i56 @ret7()
Seven ret7(void) { return (Seven){"abcdefg"}; }

// CHECK-AIX-LABEL: define{{.*}} void @ret8(ptr noalias sret(%struct.Eight) {{[^,]*}})
// CHECK-AIX-LABEL: define{{.*}} void @ret8(ptr dead_on_unwind noalias writable sret(%struct.Eight) {{[^,]*}})
// CHECK-SVR4-LABEL: define{{.*}} i64 @ret8()
Eight ret8(void) { return (Eight){123, 'a'}; }

// CHECK-AIX-LABEL: define{{.*}} void @ret9(ptr noalias sret(%struct.Nine) {{[^,]*}})
// CHECK-SVR4-LABEL: define{{.*}} void @ret9(ptr noalias sret(%struct.Nine) {{[^,]*}})
// CHECK-AIX-LABEL: define{{.*}} void @ret9(ptr dead_on_unwind noalias writable sret(%struct.Nine) {{[^,]*}})
// CHECK-SVR4-LABEL: define{{.*}} void @ret9(ptr dead_on_unwind noalias writable sret(%struct.Nine) {{[^,]*}})
Nine ret9(void) { return (Nine){"abcdefghi"}; }
Loading