Skip to content

Commit f205aef

Browse files
SC llvm teamSC llvm team
SC llvm team
authored and
SC llvm team
committed
Merged main:87e11ecbaec9 into amd-gfx:e761c8ea3c3a
Local branch amd-gfx e761c8e Merged main:f8ced20ad3e8 into amd-gfx:3887b0542d33 Remote branch main 87e11ec Revert "[clang] Add experimental option to omit the RTTI component from the vtable when -fno-rtti is used"
2 parents e761c8e + 87e11ec commit f205aef

File tree

118 files changed

+925
-5062
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

118 files changed

+925
-5062
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,6 +1621,10 @@ The following type trait primitives are supported by Clang. Those traits marked
16211621
materialized temporary object. If ``T`` is not a reference type the result
16221622
is false. Note this trait will also return false when the initialization of
16231623
``T`` from ``U`` is ill-formed.
1624+
Deprecated, use ``__reference_constructs_from_temporary``.
1625+
* ``__reference_constructs_from_temporary(T, U)`` (C++)
1626+
Returns true if a reference ``T`` can be constructed from a temporary of type
1627+
a non-cv-qualified ``U``.
16241628
* ``__underlying_type`` (C++, GNU, Microsoft)
16251629

16261630
In addition, the following expression traits are supported:

clang/include/clang/Basic/FileManager.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ class FileManager : public RefCountedBase<FileManager> {
275275
/// Open the specified file as a MemoryBuffer, returning a new
276276
/// MemoryBuffer if successful, otherwise returning null.
277277
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
278-
getBufferForFile(const FileEntry *Entry, bool isVolatile = false,
278+
getBufferForFile(FileEntryRef Entry, bool isVolatile = false,
279279
bool RequiresNullTerminator = true);
280280
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
281281
getBufferForFile(StringRef Filename, bool isVolatile = false,
@@ -327,7 +327,7 @@ class FileManager : public RefCountedBase<FileManager> {
327327
/// This is a very expensive operation, despite its results being cached,
328328
/// and should only be used when the physical layout of the file system is
329329
/// required, which is (almost) never.
330-
StringRef getCanonicalName(const FileEntry *File);
330+
StringRef getCanonicalName(FileEntryRef File);
331331

332332
private:
333333
/// Retrieve the canonical name for a given file or directory.

clang/include/clang/Basic/TokenKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ TYPE_TRAIT_1(__is_scoped_enum, IsScopedEnum, KEYCXX)
531531
TYPE_TRAIT_1(__is_referenceable, IsReferenceable, KEYCXX)
532532
TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX)
533533
TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
534+
TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX)
534535

535536
// Embarcadero Expression Traits
536537
EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX)

clang/include/clang/CodeGen/CGFunctionInfo.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,11 @@ class RequiredArgs {
527527
return NumRequired;
528528
}
529529

530+
/// Return true if the argument at a given index is required.
531+
bool isRequiredArg(unsigned argIdx) const {
532+
return argIdx == ~0U || argIdx < NumRequired;
533+
}
534+
530535
unsigned getOpaqueData() const { return NumRequired; }
531536
static RequiredArgs getFromOpaqueData(unsigned value) {
532537
if (value == ~0U) return All;

clang/include/clang/Frontend/CompilerInvocation.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,9 @@ class CowCompilerInvocation : public CompilerInvocationBase {
354354
deep_copy_assign(X);
355355
}
356356

357+
CowCompilerInvocation(CompilerInvocation &&X)
358+
: CompilerInvocationBase(std::move(X)) {}
359+
357360
// Const getters are inherited from the base class.
358361

359362
/// Mutable getters.

clang/include/clang/Lex/HeaderMap.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@ class HeaderMap : private HeaderMapImpl {
8888
public:
8989
/// This attempts to load the specified file as a header map. If it doesn't
9090
/// look like a HeaderMap, it gives up and returns null.
91-
static std::unique_ptr<HeaderMap> Create(const FileEntry *FE,
92-
FileManager &FM);
91+
static std::unique_ptr<HeaderMap> Create(FileEntryRef FE, FileManager &FM);
9392

9493
using HeaderMapImpl::dump;
9594
using HeaderMapImpl::forEachKey;

clang/lib/Basic/FileManager.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -536,8 +536,9 @@ void FileManager::fillRealPathName(FileEntry *UFE, llvm::StringRef FileName) {
536536
}
537537

538538
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
539-
FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile,
539+
FileManager::getBufferForFile(FileEntryRef FE, bool isVolatile,
540540
bool RequiresNullTerminator) {
541+
const FileEntry *Entry = &FE.getFileEntry();
541542
// If the content is living on the file entry, return a reference to it.
542543
if (Entry->Content)
543544
return llvm::MemoryBuffer::getMemBuffer(Entry->Content->getMemBufferRef());
@@ -548,7 +549,7 @@ FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile,
548549
if (isVolatile || Entry->isNamedPipe())
549550
FileSize = -1;
550551

551-
StringRef Filename = Entry->getName();
552+
StringRef Filename = FE.getName();
552553
// If the file is already open, use the open file descriptor.
553554
if (Entry->File) {
554555
auto Result = Entry->File->getBuffer(Filename, FileSize,
@@ -635,8 +636,8 @@ StringRef FileManager::getCanonicalName(DirectoryEntryRef Dir) {
635636
return getCanonicalName(Dir, Dir.getName());
636637
}
637638

638-
StringRef FileManager::getCanonicalName(const FileEntry *File) {
639-
return getCanonicalName(File, File->getName());
639+
StringRef FileManager::getCanonicalName(FileEntryRef File) {
640+
return getCanonicalName(File, File.getName());
640641
}
641642

642643
StringRef FileManager::getCanonicalName(const void *Entry, StringRef Name) {

clang/lib/CodeGen/Targets/X86.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,15 @@ static ABIArgInfo getDirectX86Hva(llvm::Type* T = nullptr) {
8787
/// Similar to llvm::CCState, but for Clang.
8888
struct CCState {
8989
CCState(CGFunctionInfo &FI)
90-
: IsPreassigned(FI.arg_size()), CC(FI.getCallingConvention()) {}
90+
: IsPreassigned(FI.arg_size()), CC(FI.getCallingConvention()),
91+
Required(FI.getRequiredArgs()), IsDelegateCall(FI.isDelegateCall()) {}
9192

9293
llvm::SmallBitVector IsPreassigned;
9394
unsigned CC = CallingConv::CC_C;
9495
unsigned FreeRegs = 0;
9596
unsigned FreeSSERegs = 0;
97+
RequiredArgs Required;
98+
bool IsDelegateCall = false;
9699
};
97100

98101
/// X86_32ABIInfo - The X86-32 ABI information.
@@ -141,7 +144,7 @@ class X86_32ABIInfo : public ABIInfo {
141144
Class classify(QualType Ty) const;
142145
ABIArgInfo classifyReturnType(QualType RetTy, CCState &State) const;
143146
ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State,
144-
bool isDelegateCall) const;
147+
unsigned ArgIndex) const;
145148

146149
/// Updates the number of available free registers, returns
147150
/// true if any registers were allocated.
@@ -739,7 +742,7 @@ void X86_32ABIInfo::runVectorCallFirstPass(CGFunctionInfo &FI, CCState &State) c
739742
}
740743

741744
ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State,
742-
bool isDelegateCall) const {
745+
unsigned ArgIndex) const {
743746
// FIXME: Set alignment on indirect arguments.
744747
bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
745748
bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
@@ -754,7 +757,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State,
754757
CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
755758
if (RAA == CGCXXABI::RAA_Indirect) {
756759
return getIndirectResult(Ty, false, State);
757-
} else if (isDelegateCall) {
760+
} else if (State.IsDelegateCall) {
758761
// Avoid having different alignments on delegate call args by always
759762
// setting the alignment to 4, which is what we do for inallocas.
760763
ABIArgInfo Res = getIndirectResult(Ty, false, State);
@@ -812,11 +815,12 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State,
812815
}
813816
llvm::IntegerType *PaddingType = NeedsPadding ? Int32 : nullptr;
814817

815-
// Pass over-aligned aggregates on Windows indirectly. This behavior was
816-
// added in MSVC 2015. Use the required alignment from the record layout,
817-
// since that may be less than the regular type alignment, and types with
818-
// required alignment of less than 4 bytes are not passed indirectly.
819-
if (IsWin32StructABI) {
818+
// Pass over-aligned aggregates to non-variadic functions on Windows
819+
// indirectly. This behavior was added in MSVC 2015. Use the required
820+
// alignment from the record layout, since that may be less than the
821+
// regular type alignment, and types with required alignment of less than 4
822+
// bytes are not passed indirectly.
823+
if (IsWin32StructABI && State.Required.isRequiredArg(ArgIndex)) {
820824
unsigned AlignInBits = 0;
821825
if (RT) {
822826
const ASTRecordLayout &Layout =
@@ -942,13 +946,13 @@ void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const {
942946

943947
bool UsedInAlloca = false;
944948
MutableArrayRef<CGFunctionInfoArgInfo> Args = FI.arguments();
945-
for (int I = 0, E = Args.size(); I < E; ++I) {
949+
for (unsigned I = 0, E = Args.size(); I < E; ++I) {
946950
// Skip arguments that have already been assigned.
947951
if (State.IsPreassigned.test(I))
948952
continue;
949953

950954
Args[I].info =
951-
classifyArgumentType(Args[I].type, State, FI.isDelegateCall());
955+
classifyArgumentType(Args[I].type, State, I);
952956
UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca);
953957
}
954958

clang/lib/ExtractAPI/ExtractAPIConsumer.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,17 +177,17 @@ struct LocationFileChecker {
177177
if (FID.isInvalid())
178178
return false;
179179

180-
const auto *File = SM.getFileEntryForID(FID);
180+
OptionalFileEntryRef File = SM.getFileEntryRefForID(FID);
181181
if (!File)
182182
return false;
183183

184-
if (KnownFileEntries.count(File))
184+
if (KnownFileEntries.count(*File))
185185
return true;
186186

187-
if (ExternalFileEntries.count(File))
187+
if (ExternalFileEntries.count(*File))
188188
return false;
189189

190-
StringRef FileName = SM.getFileManager().getCanonicalName(File);
190+
StringRef FileName = SM.getFileManager().getCanonicalName(*File);
191191

192192
// Try to reduce the include name the same way we tried to include it.
193193
bool IsQuoted = false;
@@ -197,13 +197,13 @@ struct LocationFileChecker {
197197
return KnownFile.first.equals(*IncludeName) &&
198198
KnownFile.second == IsQuoted;
199199
})) {
200-
KnownFileEntries.insert(File);
200+
KnownFileEntries.insert(*File);
201201
return true;
202202
}
203203

204204
// Record that the file was not found to avoid future reverse lookup for
205205
// the same file.
206-
ExternalFileEntries.insert(File);
206+
ExternalFileEntries.insert(*File);
207207
return false;
208208
}
209209

clang/lib/Frontend/DependencyFile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ void DependencyCollector::maybeAddDependency(StringRef Filename,
159159
bool IsMissing) {
160160
if (sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing)) {
161161
if (IsSystem && FileMgr && shouldCanonicalizeSystemDependencies()) {
162-
if (auto F = FileMgr->getFile(Filename))
162+
if (auto F = FileMgr->getOptionalFileRef(Filename))
163163
Filename = FileMgr->getCanonicalName(*F);
164164
}
165165
addDependency(Filename);

clang/lib/Frontend/SARIFDiagnostic.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,7 @@ SARIFDiagnostic::addDiagnosticLevelToRule(SarifRule Rule,
164164
llvm::StringRef SARIFDiagnostic::emitFilename(StringRef Filename,
165165
const SourceManager &SM) {
166166
if (DiagOpts->AbsolutePath) {
167-
llvm::ErrorOr<const FileEntry *> File =
168-
SM.getFileManager().getFile(Filename);
167+
auto File = SM.getFileManager().getOptionalFileRef(Filename);
169168
if (File) {
170169
// We want to print a simplified absolute path, i. e. without "dots".
171170
//
@@ -182,7 +181,7 @@ llvm::StringRef SARIFDiagnostic::emitFilename(StringRef Filename,
182181
// on Windows we can just use llvm::sys::path::remove_dots(), because,
183182
// on that system, both aforementioned paths point to the same place.
184183
#ifdef _WIN32
185-
SmallString<256> TmpFilename = (*File)->getName();
184+
SmallString<256> TmpFilename = File->getName();
186185
llvm::sys::fs::make_absolute(TmpFilename);
187186
llvm::sys::path::native(TmpFilename);
188187
llvm::sys::path::remove_dots(TmpFilename, /* remove_dot_dot */ true);

clang/lib/Frontend/TextDiagnostic.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) {
736736
SmallString<4096> TmpFilename;
737737
#endif
738738
if (DiagOpts->AbsolutePath) {
739-
auto File = SM.getFileManager().getFile(Filename);
739+
auto File = SM.getFileManager().getOptionalFileRef(Filename);
740740
if (File) {
741741
// We want to print a simplified absolute path, i. e. without "dots".
742742
//
@@ -753,7 +753,7 @@ void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) {
753753
// on Windows we can just use llvm::sys::path::remove_dots(), because,
754754
// on that system, both aforementioned paths point to the same place.
755755
#ifdef _WIN32
756-
TmpFilename = (*File)->getName();
756+
TmpFilename = File->getName();
757757
llvm::sys::fs::make_absolute(TmpFilename);
758758
llvm::sys::path::native(TmpFilename);
759759
llvm::sys::path::remove_dots(TmpFilename, /* remove_dot_dot */ true);

clang/lib/Lex/HeaderMap.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,9 @@ static inline unsigned HashHMapKey(StringRef Str) {
4848
/// map. If it doesn't look like a HeaderMap, it gives up and returns null.
4949
/// If it looks like a HeaderMap but is obviously corrupted, it puts a reason
5050
/// into the string error argument and returns null.
51-
std::unique_ptr<HeaderMap> HeaderMap::Create(const FileEntry *FE,
52-
FileManager &FM) {
51+
std::unique_ptr<HeaderMap> HeaderMap::Create(FileEntryRef FE, FileManager &FM) {
5352
// If the file is too small to be a header map, ignore it.
54-
unsigned FileSize = FE->getSize();
53+
unsigned FileSize = FE.getSize();
5554
if (FileSize <= sizeof(HMapHeader)) return nullptr;
5655

5756
auto FileBuffer = FM.getBufferForFile(FE);

clang/lib/Lex/PPMacroExpansion.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,6 +1695,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
16951695
.Case("__array_rank", true)
16961696
.Case("__array_extent", true)
16971697
.Case("__reference_binds_to_temporary", true)
1698+
.Case("__reference_constructs_from_temporary", true)
16981699
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) .Case("__" #Trait, true)
16991700
#include "clang/Basic/TransformTypeTraits.def"
17001701
.Default(false);

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1655,7 +1655,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
16551655
tok::kw___is_union,
16561656
tok::kw___is_unsigned,
16571657
tok::kw___is_void,
1658-
tok::kw___is_volatile))
1658+
tok::kw___is_volatile,
1659+
tok::kw___reference_binds_to_temporary,
1660+
tok::kw___reference_constructs_from_temporary))
16591661
// GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the
16601662
// name of struct templates, but some are keywords in GCC >= 4.3
16611663
// and Clang. Therefore, when we see the token sequence "struct

clang/lib/Parse/ParseExpr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
11281128
REVERTIBLE_TYPE_TRAIT(__is_unsigned);
11291129
REVERTIBLE_TYPE_TRAIT(__is_void);
11301130
REVERTIBLE_TYPE_TRAIT(__is_volatile);
1131+
REVERTIBLE_TYPE_TRAIT(__reference_binds_to_temporary);
1132+
REVERTIBLE_TYPE_TRAIT(__reference_constructs_from_temporary);
11311133
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \
11321134
REVERTIBLE_TYPE_TRAIT(RTT_JOIN(__, Trait));
11331135
#include "clang/Basic/TransformTypeTraits.def"

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5410,14 +5410,15 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind,
54105410
if (Kind <= UTT_Last)
54115411
return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType());
54125412

5413-
// Evaluate BTT_ReferenceBindsToTemporary alongside the IsConstructible
5414-
// traits to avoid duplication.
5415-
if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary)
5413+
// Evaluate ReferenceBindsToTemporary and ReferenceConstructsFromTemporary
5414+
// alongside the IsConstructible traits to avoid duplication.
5415+
if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary && Kind != BTT_ReferenceConstructsFromTemporary)
54165416
return EvaluateBinaryTypeTrait(S, Kind, Args[0]->getType(),
54175417
Args[1]->getType(), RParenLoc);
54185418

54195419
switch (Kind) {
54205420
case clang::BTT_ReferenceBindsToTemporary:
5421+
case clang::BTT_ReferenceConstructsFromTemporary:
54215422
case clang::TT_IsConstructible:
54225423
case clang::TT_IsNothrowConstructible:
54235424
case clang::TT_IsTriviallyConstructible: {
@@ -5494,11 +5495,23 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind,
54945495
if (Kind == clang::TT_IsConstructible)
54955496
return true;
54965497

5497-
if (Kind == clang::BTT_ReferenceBindsToTemporary) {
5498+
if (Kind == clang::BTT_ReferenceBindsToTemporary || Kind == clang::BTT_ReferenceConstructsFromTemporary) {
54985499
if (!T->isReferenceType())
54995500
return false;
55005501

5501-
return !Init.isDirectReferenceBinding();
5502+
if (!Init.isDirectReferenceBinding())
5503+
return true;
5504+
5505+
if (Kind == clang::BTT_ReferenceBindsToTemporary)
5506+
return false;
5507+
5508+
QualType U = Args[1]->getType();
5509+
if (U->isReferenceType())
5510+
return false;
5511+
5512+
QualType TPtr = S.Context.getPointerType(S.BuiltinRemoveReference(T, UnaryTransformType::RemoveCVRef, {}));
5513+
QualType UPtr = S.Context.getPointerType(S.BuiltinRemoveReference(U, UnaryTransformType::RemoveCVRef, {}));
5514+
return EvaluateBinaryTypeTrait(S, TypeTrait::BTT_IsConvertibleTo, UPtr, TPtr, RParenLoc);
55025515
}
55035516

55045517
if (Kind == clang::TT_IsNothrowConstructible)

clang/lib/Serialization/ASTReader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2501,7 +2501,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
25012501
// accept the cached file as legit.
25022502
if (ValidateASTInputFilesContent &&
25032503
StoredContentHash != static_cast<uint64_t>(llvm::hash_code(-1))) {
2504-
auto MemBuffOrError = FileMgr.getBufferForFile(File);
2504+
auto MemBuffOrError = FileMgr.getBufferForFile(*File);
25052505
if (!MemBuffOrError) {
25062506
if (!Complain)
25072507
return MTimeChange;

clang/lib/Serialization/ModuleManager.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
209209
//
210210
// RequiresNullTerminator is false because module files don't need it, and
211211
// this allows the file to still be mmapped.
212-
Buf = FileMgr.getBufferForFile(NewModule->File,
212+
Buf = FileMgr.getBufferForFile(*NewModule->File,
213213
/*IsVolatile=*/true,
214214
/*RequiresNullTerminator=*/false);
215215
}

clang/test/CodeGen/X86/x86_32-arguments-win32.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,32 @@ void pass_underaligned_record_field() {
128128
// CHECK: call void @receive_falign1(i64 {{[^,)]*}})
129129
// CHECK: call void @receive_falign4(i64 {{[^,)]*}})
130130
// CHECK: call void @receive_falign8(ptr {{[^,)]*}})
131+
132+
struct __declspec(align(8)) BigAligned {
133+
int big[5];
134+
};
135+
136+
void receive_aligned_variadic(int f, ...);
137+
void pass_aligned_variadic() {
138+
struct Align8 a8 = {42};
139+
struct FieldAlign8 f8 = {42};
140+
struct BigAligned big;
141+
receive_aligned_variadic(1, a8, f8, big);
142+
}
143+
// MSVC doesn't pass aligned objects to variadic functions indirectly.
144+
// CHECK-LABEL: define dso_local void @pass_aligned_variadic()
145+
// CHECK: call void (i32, ...) @receive_aligned_variadic(i32 noundef 1, i64 %{{[^,]*}}, i64 %{{[^,]*}}, ptr noundef byval(%struct.BigAligned) align 4 %{{[^)]*}})
146+
147+
148+
void receive_fixed_align_variadic(struct BigAligned big, ...);
149+
void pass_fixed_align_variadic() {
150+
struct BigAligned big;
151+
receive_fixed_align_variadic(big, 42);
152+
}
153+
// MSVC emits error C2719 and C3916 when receiving and passing arguments with
154+
// required alignment greater than 4 to the fixed part of a variadic function
155+
// prototype, but it's actually easier to just implement this functionality
156+
// correctly in Clang than it is to be bug for bug compatible, so we pass such
157+
// arguments indirectly.
158+
// CHECK-LABEL: define dso_local void @pass_fixed_align_variadic()
159+
// CHECK: call void (ptr, ...) @receive_fixed_align_variadic(ptr noundef %{{[^)]*}}, i32 noundef 42)

0 commit comments

Comments
 (0)