Skip to content

Commit

Permalink
Merged main:87e11ecbaec9 into amd-gfx:e761c8ea3c3a
Browse files Browse the repository at this point in the history
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"
  • Loading branch information
SC llvm team authored and SC llvm team committed Sep 13, 2023
2 parents e761c8e + 87e11ec commit f205aef
Show file tree
Hide file tree
Showing 118 changed files with 925 additions and 5,062 deletions.
4 changes: 4 additions & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1621,6 +1621,10 @@ The following type trait primitives are supported by Clang. Those traits marked
materialized temporary object. If ``T`` is not a reference type the result
is false. Note this trait will also return false when the initialization of
``T`` from ``U`` is ill-formed.
Deprecated, use ``__reference_constructs_from_temporary``.
* ``__reference_constructs_from_temporary(T, U)`` (C++)
Returns true if a reference ``T`` can be constructed from a temporary of type
a non-cv-qualified ``U``.
* ``__underlying_type`` (C++, GNU, Microsoft)

In addition, the following expression traits are supported:
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/FileManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ class FileManager : public RefCountedBase<FileManager> {
/// Open the specified file as a MemoryBuffer, returning a new
/// MemoryBuffer if successful, otherwise returning null.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBufferForFile(const FileEntry *Entry, bool isVolatile = false,
getBufferForFile(FileEntryRef Entry, bool isVolatile = false,
bool RequiresNullTerminator = true);
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBufferForFile(StringRef Filename, bool isVolatile = false,
Expand Down Expand Up @@ -327,7 +327,7 @@ class FileManager : public RefCountedBase<FileManager> {
/// This is a very expensive operation, despite its results being cached,
/// and should only be used when the physical layout of the file system is
/// required, which is (almost) never.
StringRef getCanonicalName(const FileEntry *File);
StringRef getCanonicalName(FileEntryRef File);

private:
/// Retrieve the canonical name for a given file or directory.
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ TYPE_TRAIT_1(__is_scoped_enum, IsScopedEnum, KEYCXX)
TYPE_TRAIT_1(__is_referenceable, IsReferenceable, KEYCXX)
TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX)
TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX)

// Embarcadero Expression Traits
EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX)
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/CodeGen/CGFunctionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,11 @@ class RequiredArgs {
return NumRequired;
}

/// Return true if the argument at a given index is required.
bool isRequiredArg(unsigned argIdx) const {
return argIdx == ~0U || argIdx < NumRequired;
}

unsigned getOpaqueData() const { return NumRequired; }
static RequiredArgs getFromOpaqueData(unsigned value) {
if (value == ~0U) return All;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Frontend/CompilerInvocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,9 @@ class CowCompilerInvocation : public CompilerInvocationBase {
deep_copy_assign(X);
}

CowCompilerInvocation(CompilerInvocation &&X)
: CompilerInvocationBase(std::move(X)) {}

// Const getters are inherited from the base class.

/// Mutable getters.
Expand Down
3 changes: 1 addition & 2 deletions clang/include/clang/Lex/HeaderMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ class HeaderMap : private HeaderMapImpl {
public:
/// This attempts to load the specified file as a header map. If it doesn't
/// look like a HeaderMap, it gives up and returns null.
static std::unique_ptr<HeaderMap> Create(const FileEntry *FE,
FileManager &FM);
static std::unique_ptr<HeaderMap> Create(FileEntryRef FE, FileManager &FM);

using HeaderMapImpl::dump;
using HeaderMapImpl::forEachKey;
Expand Down
9 changes: 5 additions & 4 deletions clang/lib/Basic/FileManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,8 +536,9 @@ void FileManager::fillRealPathName(FileEntry *UFE, llvm::StringRef FileName) {
}

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

StringRef Filename = Entry->getName();
StringRef Filename = FE.getName();
// If the file is already open, use the open file descriptor.
if (Entry->File) {
auto Result = Entry->File->getBuffer(Filename, FileSize,
Expand Down Expand Up @@ -635,8 +636,8 @@ StringRef FileManager::getCanonicalName(DirectoryEntryRef Dir) {
return getCanonicalName(Dir, Dir.getName());
}

StringRef FileManager::getCanonicalName(const FileEntry *File) {
return getCanonicalName(File, File->getName());
StringRef FileManager::getCanonicalName(FileEntryRef File) {
return getCanonicalName(File, File.getName());
}

StringRef FileManager::getCanonicalName(const void *Entry, StringRef Name) {
Expand Down
26 changes: 15 additions & 11 deletions clang/lib/CodeGen/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,15 @@ static ABIArgInfo getDirectX86Hva(llvm::Type* T = nullptr) {
/// Similar to llvm::CCState, but for Clang.
struct CCState {
CCState(CGFunctionInfo &FI)
: IsPreassigned(FI.arg_size()), CC(FI.getCallingConvention()) {}
: IsPreassigned(FI.arg_size()), CC(FI.getCallingConvention()),
Required(FI.getRequiredArgs()), IsDelegateCall(FI.isDelegateCall()) {}

llvm::SmallBitVector IsPreassigned;
unsigned CC = CallingConv::CC_C;
unsigned FreeRegs = 0;
unsigned FreeSSERegs = 0;
RequiredArgs Required;
bool IsDelegateCall = false;
};

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

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

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

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

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

Args[I].info =
classifyArgumentType(Args[I].type, State, FI.isDelegateCall());
classifyArgumentType(Args[I].type, State, I);
UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca);
}

Expand Down
12 changes: 6 additions & 6 deletions clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,17 +177,17 @@ struct LocationFileChecker {
if (FID.isInvalid())
return false;

const auto *File = SM.getFileEntryForID(FID);
OptionalFileEntryRef File = SM.getFileEntryRefForID(FID);
if (!File)
return false;

if (KnownFileEntries.count(File))
if (KnownFileEntries.count(*File))
return true;

if (ExternalFileEntries.count(File))
if (ExternalFileEntries.count(*File))
return false;

StringRef FileName = SM.getFileManager().getCanonicalName(File);
StringRef FileName = SM.getFileManager().getCanonicalName(*File);

// Try to reduce the include name the same way we tried to include it.
bool IsQuoted = false;
Expand All @@ -197,13 +197,13 @@ struct LocationFileChecker {
return KnownFile.first.equals(*IncludeName) &&
KnownFile.second == IsQuoted;
})) {
KnownFileEntries.insert(File);
KnownFileEntries.insert(*File);
return true;
}

// Record that the file was not found to avoid future reverse lookup for
// the same file.
ExternalFileEntries.insert(File);
ExternalFileEntries.insert(*File);
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Frontend/DependencyFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ void DependencyCollector::maybeAddDependency(StringRef Filename,
bool IsMissing) {
if (sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing)) {
if (IsSystem && FileMgr && shouldCanonicalizeSystemDependencies()) {
if (auto F = FileMgr->getFile(Filename))
if (auto F = FileMgr->getOptionalFileRef(Filename))
Filename = FileMgr->getCanonicalName(*F);
}
addDependency(Filename);
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/Frontend/SARIFDiagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,7 @@ SARIFDiagnostic::addDiagnosticLevelToRule(SarifRule Rule,
llvm::StringRef SARIFDiagnostic::emitFilename(StringRef Filename,
const SourceManager &SM) {
if (DiagOpts->AbsolutePath) {
llvm::ErrorOr<const FileEntry *> File =
SM.getFileManager().getFile(Filename);
auto File = SM.getFileManager().getOptionalFileRef(Filename);
if (File) {
// We want to print a simplified absolute path, i. e. without "dots".
//
Expand All @@ -182,7 +181,7 @@ llvm::StringRef SARIFDiagnostic::emitFilename(StringRef Filename,
// on Windows we can just use llvm::sys::path::remove_dots(), because,
// on that system, both aforementioned paths point to the same place.
#ifdef _WIN32
SmallString<256> TmpFilename = (*File)->getName();
SmallString<256> TmpFilename = File->getName();
llvm::sys::fs::make_absolute(TmpFilename);
llvm::sys::path::native(TmpFilename);
llvm::sys::path::remove_dots(TmpFilename, /* remove_dot_dot */ true);
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Frontend/TextDiagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) {
SmallString<4096> TmpFilename;
#endif
if (DiagOpts->AbsolutePath) {
auto File = SM.getFileManager().getFile(Filename);
auto File = SM.getFileManager().getOptionalFileRef(Filename);
if (File) {
// We want to print a simplified absolute path, i. e. without "dots".
//
Expand All @@ -753,7 +753,7 @@ void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) {
// on Windows we can just use llvm::sys::path::remove_dots(), because,
// on that system, both aforementioned paths point to the same place.
#ifdef _WIN32
TmpFilename = (*File)->getName();
TmpFilename = File->getName();
llvm::sys::fs::make_absolute(TmpFilename);
llvm::sys::path::native(TmpFilename);
llvm::sys::path::remove_dots(TmpFilename, /* remove_dot_dot */ true);
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/Lex/HeaderMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,9 @@ static inline unsigned HashHMapKey(StringRef Str) {
/// map. If it doesn't look like a HeaderMap, it gives up and returns null.
/// If it looks like a HeaderMap but is obviously corrupted, it puts a reason
/// into the string error argument and returns null.
std::unique_ptr<HeaderMap> HeaderMap::Create(const FileEntry *FE,
FileManager &FM) {
std::unique_ptr<HeaderMap> HeaderMap::Create(FileEntryRef FE, FileManager &FM) {
// If the file is too small to be a header map, ignore it.
unsigned FileSize = FE->getSize();
unsigned FileSize = FE.getSize();
if (FileSize <= sizeof(HMapHeader)) return nullptr;

auto FileBuffer = FM.getBufferForFile(FE);
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Lex/PPMacroExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1695,6 +1695,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
.Case("__array_rank", true)
.Case("__array_extent", true)
.Case("__reference_binds_to_temporary", true)
.Case("__reference_constructs_from_temporary", true)
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) .Case("__" #Trait, true)
#include "clang/Basic/TransformTypeTraits.def"
.Default(false);
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1655,7 +1655,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
tok::kw___is_union,
tok::kw___is_unsigned,
tok::kw___is_void,
tok::kw___is_volatile))
tok::kw___is_volatile,
tok::kw___reference_binds_to_temporary,
tok::kw___reference_constructs_from_temporary))
// GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the
// name of struct templates, but some are keywords in GCC >= 4.3
// and Clang. Therefore, when we see the token sequence "struct
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
REVERTIBLE_TYPE_TRAIT(__is_unsigned);
REVERTIBLE_TYPE_TRAIT(__is_void);
REVERTIBLE_TYPE_TRAIT(__is_volatile);
REVERTIBLE_TYPE_TRAIT(__reference_binds_to_temporary);
REVERTIBLE_TYPE_TRAIT(__reference_constructs_from_temporary);
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \
REVERTIBLE_TYPE_TRAIT(RTT_JOIN(__, Trait));
#include "clang/Basic/TransformTypeTraits.def"
Expand Down
23 changes: 18 additions & 5 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5410,14 +5410,15 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind,
if (Kind <= UTT_Last)
return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType());

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

switch (Kind) {
case clang::BTT_ReferenceBindsToTemporary:
case clang::BTT_ReferenceConstructsFromTemporary:
case clang::TT_IsConstructible:
case clang::TT_IsNothrowConstructible:
case clang::TT_IsTriviallyConstructible: {
Expand Down Expand Up @@ -5494,11 +5495,23 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind,
if (Kind == clang::TT_IsConstructible)
return true;

if (Kind == clang::BTT_ReferenceBindsToTemporary) {
if (Kind == clang::BTT_ReferenceBindsToTemporary || Kind == clang::BTT_ReferenceConstructsFromTemporary) {
if (!T->isReferenceType())
return false;

return !Init.isDirectReferenceBinding();
if (!Init.isDirectReferenceBinding())
return true;

if (Kind == clang::BTT_ReferenceBindsToTemporary)
return false;

QualType U = Args[1]->getType();
if (U->isReferenceType())
return false;

QualType TPtr = S.Context.getPointerType(S.BuiltinRemoveReference(T, UnaryTransformType::RemoveCVRef, {}));
QualType UPtr = S.Context.getPointerType(S.BuiltinRemoveReference(U, UnaryTransformType::RemoveCVRef, {}));
return EvaluateBinaryTypeTrait(S, TypeTrait::BTT_IsConvertibleTo, UPtr, TPtr, RParenLoc);
}

if (Kind == clang::TT_IsNothrowConstructible)
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2501,7 +2501,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// accept the cached file as legit.
if (ValidateASTInputFilesContent &&
StoredContentHash != static_cast<uint64_t>(llvm::hash_code(-1))) {
auto MemBuffOrError = FileMgr.getBufferForFile(File);
auto MemBuffOrError = FileMgr.getBufferForFile(*File);
if (!MemBuffOrError) {
if (!Complain)
return MTimeChange;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Serialization/ModuleManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
//
// RequiresNullTerminator is false because module files don't need it, and
// this allows the file to still be mmapped.
Buf = FileMgr.getBufferForFile(NewModule->File,
Buf = FileMgr.getBufferForFile(*NewModule->File,
/*IsVolatile=*/true,
/*RequiresNullTerminator=*/false);
}
Expand Down
29 changes: 29 additions & 0 deletions clang/test/CodeGen/X86/x86_32-arguments-win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,32 @@ void pass_underaligned_record_field() {
// CHECK: call void @receive_falign1(i64 {{[^,)]*}})
// CHECK: call void @receive_falign4(i64 {{[^,)]*}})
// CHECK: call void @receive_falign8(ptr {{[^,)]*}})

struct __declspec(align(8)) BigAligned {
int big[5];
};

void receive_aligned_variadic(int f, ...);
void pass_aligned_variadic() {
struct Align8 a8 = {42};
struct FieldAlign8 f8 = {42};
struct BigAligned big;
receive_aligned_variadic(1, a8, f8, big);
}
// MSVC doesn't pass aligned objects to variadic functions indirectly.
// CHECK-LABEL: define dso_local void @pass_aligned_variadic()
// CHECK: call void (i32, ...) @receive_aligned_variadic(i32 noundef 1, i64 %{{[^,]*}}, i64 %{{[^,]*}}, ptr noundef byval(%struct.BigAligned) align 4 %{{[^)]*}})


void receive_fixed_align_variadic(struct BigAligned big, ...);
void pass_fixed_align_variadic() {
struct BigAligned big;
receive_fixed_align_variadic(big, 42);
}
// MSVC emits error C2719 and C3916 when receiving and passing arguments with
// required alignment greater than 4 to the fixed part of a variadic function
// prototype, but it's actually easier to just implement this functionality
// correctly in Clang than it is to be bug for bug compatible, so we pass such
// arguments indirectly.
// CHECK-LABEL: define dso_local void @pass_fixed_align_variadic()
// CHECK: call void (ptr, ...) @receive_fixed_align_variadic(ptr noundef %{{[^)]*}}, i32 noundef 42)
Loading

0 comments on commit f205aef

Please sign in to comment.