41 changes: 41 additions & 0 deletions clang/include/clang/Basic/arm_sme.td
Original file line number Diff line number Diff line change
Expand Up @@ -764,4 +764,45 @@ let SMETargetGuard = "sme-f16f16" in {
[ImmCheck<0, ImmCheck0_1>]>;
}


multiclass ZAReadz<string n_suffix, string vg_num, string t, string i_prefix, list<ImmCheck> ch> {
let SMETargetGuard = "sme2p1" in {
def NAME # _H : SInst<"svreadz_hor_" # n_suffix # "_{d}_vg" # vg_num, vg_num # "im", t,
MergeNone, i_prefix # "_horiz_x" # vg_num,
[IsStreaming, IsInOutZA], ch>;

def NAME # _V : SInst<"svreadz_ver_" # n_suffix # "_{d}_vg" # vg_num, vg_num # "im", t,
MergeNone, i_prefix # "_vert_x" #vg_num,
[IsStreaming, IsInOutZA], ch>;
}
}

defm SVREADZ_ZA8_X2 : ZAReadz<"za8", "2", "cUc", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_0>]>;
defm SVREADZ_ZA16_X2 : ZAReadz<"za16", "2", "sUshb", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_1>]>;
defm SVREADZ_ZA32_X2 : ZAReadz<"za32", "2", "iUif", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_3>]>;
defm SVREADZ_ZA64_X2 : ZAReadz<"za64", "2", "lUld", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_7>]>;

defm SVREADZ_ZA8_X4 : ZAReadz<"za8", "4", "cUc", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_0>]>;
defm SVREADZ_ZA16_X4 : ZAReadz<"za16", "4", "sUshb", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_1>]>;
defm SVREADZ_ZA32_X4 : ZAReadz<"za32", "4", "iUif", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_3>]>;
defm SVREADZ_ZA64_X4 : ZAReadz<"za64", "4", "lUld", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_7>]>;


multiclass ZAReadzSingle<string n_suffix, string t, string i_prefix, list<ImmCheck> ch> {
let SMETargetGuard = "sme2p1" in {
def NAME # _H : SInst<"svreadz_hor_" # n_suffix # "_{d}", "dim", t,
MergeNone, i_prefix # "_horiz",
[IsStreaming, IsInOutZA], ch>;

def NAME # _V : SInst<"svreadz_ver_" # n_suffix # "_{d}", "dim", t,
MergeNone, i_prefix # "_vert",
[IsStreaming, IsInOutZA], ch>;
}
}

defm SVREADZ_ZA8 : ZAReadzSingle<"za8", "cUc", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_0>]>;
defm SVREADZ_ZA16 : ZAReadzSingle<"za16", "sUshb", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_1>]>;
defm SVREADZ_ZA32 : ZAReadzSingle<"za32", "iUif", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_3>]>;
defm SVREADZ_ZA64 : ZAReadzSingle<"za64", "lUld", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_7>]>;
defm SVREADZ_ZA128 : ZAReadzSingle<"za128", "csilUcUiUsUlbhfd", "aarch64_sme_readz_q", [ImmCheck<0, ImmCheck0_15>]>;
} // let SVETargetGuard = InvalidMode
4 changes: 4 additions & 0 deletions clang/include/clang/CodeGen/CodeGenABITypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class CXXConstructorDecl;
class CXXDestructorDecl;
class CXXRecordDecl;
class CXXMethodDecl;
class GlobalDecl;
class ObjCMethodDecl;
class ObjCProtocolDecl;

Expand Down Expand Up @@ -104,6 +105,9 @@ llvm::Type *convertTypeForMemory(CodeGenModule &CGM, QualType T);
unsigned getLLVMFieldNumber(CodeGenModule &CGM,
const RecordDecl *RD, const FieldDecl *FD);

/// Return a declaration discriminator for the given global decl.
uint16_t getPointerAuthDeclDiscriminator(CodeGenModule &CGM, GlobalDecl GD);

/// Given the language and code-generation options that Clang was configured
/// with, set the default LLVM IR attributes for a function definition.
/// The attributes set here are mostly global target-configuration and
Expand Down
10 changes: 9 additions & 1 deletion clang/include/clang/CodeGen/ConstantInitBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
#include <vector>

namespace clang {
namespace CodeGen {
class GlobalDecl;
class PointerAuthSchema;
class QualType;

namespace CodeGen {
class CodeGenModule;

/// A convenience builder class for complex constant initializers,
Expand Down Expand Up @@ -199,6 +202,11 @@ class ConstantAggregateBuilderBase {
add(llvm::ConstantInt::get(intTy, value, isSigned));
}

/// Add a signed pointer using the given pointer authentication schema.
void addSignedPointer(llvm::Constant *Pointer,
const PointerAuthSchema &Schema, GlobalDecl CalleeDecl,
QualType CalleeType);

/// Add a null pointer of a specific type.
void addNullPointer(llvm::PointerType *ptrTy) {
add(llvm::ConstantPointerNull::get(ptrTy));
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/CodeGen/ModuleBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"

namespace llvm {
class Constant;
Expand All @@ -27,6 +28,9 @@ namespace llvm {
}
}

// Prefix of the name of the artificial inline frame.
inline constexpr llvm::StringRef ClangTrapPrefix = "__clang_trap_msg";

namespace clang {
class CodeGenOptions;
class CoverageSourceInfo;
Expand Down
10 changes: 9 additions & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -5535,7 +5535,10 @@ def print_prog_name_EQ : Joined<["-", "--"], "print-prog-name=">,
Visibility<[ClangOption, CLOption]>;
def print_resource_dir : Flag<["-", "--"], "print-resource-dir">,
HelpText<"Print the resource directory pathname">,
Visibility<[ClangOption, CLOption]>;
HelpTextForVariants<[FlangOption],
"Print the resource directory pathname that contains lib and "
"include directories with the runtime libraries and MODULE files.">,
Visibility<[ClangOption, CLOption, FlangOption]>;
def print_search_dirs : Flag<["-", "--"], "print-search-dirs">,
HelpText<"Print the paths used for finding libraries and programs">,
Visibility<[ClangOption, CLOption]>;
Expand Down Expand Up @@ -5710,6 +5713,11 @@ def print_supported_extensions : Flag<["-", "--"], "print-supported-extensions">
Visibility<[ClangOption, CC1Option, CLOption]>,
HelpText<"Print supported -march extensions (RISC-V, AArch64 and ARM only)">,
MarshallingInfoFlag<FrontendOpts<"PrintSupportedExtensions">>;
def print_enabled_extensions : Flag<["-", "--"], "print-enabled-extensions">,
Visibility<[ClangOption, CC1Option, CLOption]>,
HelpText<"Print the extensions enabled by the given target and -march/-mcpu options."
" (AArch64 only)">,
MarshallingInfoFlag<FrontendOpts<"PrintEnabledExtensions">>;
def : Flag<["-"], "mcpu=help">, Alias<print_supported_cpus>;
def : Flag<["-"], "mtune=help">, Alias<print_supported_cpus>;
def time : Flag<["-"], "time">,
Expand Down
56 changes: 15 additions & 41 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -3095,49 +3095,20 @@ struct FormatStyle {
bool JavaScriptWrapImports;
// clang-format on

/// Options regarding which empty lines are kept.
///
/// For example, the config below will remove empty lines at start of the
/// file, end of the file, and start of blocks.
///
/// \code
/// KeepEmptyLines:
/// AtEndOfFile: false
/// AtStartOfBlock: false
/// AtStartOfFile: false
/// \endcode
struct KeepEmptyLinesStyle {
/// Keep empty lines at end of file.
bool AtEndOfFile;
/// Keep empty lines at start of a block.
/// \code
/// true: false:
/// if (foo) { vs. if (foo) {
/// bar();
/// bar(); }
/// }
/// \endcode
bool AtStartOfBlock;
/// Keep empty lines at start of file.
bool AtStartOfFile;
bool operator==(const KeepEmptyLinesStyle &R) const {
return AtEndOfFile == R.AtEndOfFile &&
AtStartOfBlock == R.AtStartOfBlock &&
AtStartOfFile == R.AtStartOfFile;
}
};
/// Which empty lines are kept. See ``MaxEmptyLinesToKeep`` for how many
/// consecutive empty lines are kept.
/// \version 19
KeepEmptyLinesStyle KeepEmptyLines;

/// This option is deprecated. See ``AtEndOfFile`` of ``KeepEmptyLines``.
/// Keep empty lines (up to ``MaxEmptyLinesToKeep``) at end of file.
/// \version 17
// bool KeepEmptyLinesAtEOF;
bool KeepEmptyLinesAtEOF;

/// This option is deprecated. See ``AtStartOfBlock`` of ``KeepEmptyLines``.
/// If true, the empty line at the start of blocks is kept.
/// \code
/// true: false:
/// if (foo) { vs. if (foo) {
/// bar();
/// bar(); }
/// }
/// \endcode
/// \version 3.7
// bool KeepEmptyLinesAtTheStartOfBlocks;
bool KeepEmptyLinesAtTheStartOfBlocks;

/// Indentation logic for lambda bodies.
enum LambdaBodyIndentationKind : int8_t {
Expand Down Expand Up @@ -5062,7 +5033,10 @@ struct FormatStyle {
JavaImportGroups == R.JavaImportGroups &&
JavaScriptQuotes == R.JavaScriptQuotes &&
JavaScriptWrapImports == R.JavaScriptWrapImports &&
KeepEmptyLines == R.KeepEmptyLines && Language == R.Language &&
KeepEmptyLinesAtEOF == R.KeepEmptyLinesAtEOF &&
KeepEmptyLinesAtTheStartOfBlocks ==
R.KeepEmptyLinesAtTheStartOfBlocks &&
Language == R.Language &&
LambdaBodyIndentation == R.LambdaBodyIndentation &&
LineEnding == R.LineEnding && MacroBlockBegin == R.MacroBlockBegin &&
MacroBlockEnd == R.MacroBlockEnd && Macros == R.Macros &&
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,10 @@ class FrontendOptions {
LLVM_PREFERRED_TYPE(bool)
unsigned PrintSupportedExtensions : 1;

/// Print the extensions enabled for the current target.
LLVM_PREFERRED_TYPE(bool)
unsigned PrintEnabledExtensions : 1;

/// Show the -version text.
LLVM_PREFERRED_TYPE(bool)
unsigned ShowVersion : 1;
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/InstallAPI/Visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ class InstallAPIVisitor final : public ASTConsumer,
std::string getMangledName(const NamedDecl *D) const;
std::string getBackendMangledName(llvm::Twine Name) const;
std::string getMangledCXXVTableName(const CXXRecordDecl *D) const;
std::string getMangledCXXThunk(const GlobalDecl &D,
const ThunkInfo &Thunk) const;
std::string getMangledCXXThunk(const GlobalDecl &D, const ThunkInfo &Thunk,
bool ElideOverrideInfo) const;
std::string getMangledCXXRTTI(const CXXRecordDecl *D) const;
std::string getMangledCXXRTTIName(const CXXRecordDecl *D) const;
std::string getMangledCtorDtor(const CXXMethodDecl *D, int Type) const;
Expand Down
23 changes: 19 additions & 4 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -3017,24 +3017,26 @@ class Parser : public CodeCompletionHandler {
const IdentifierInfo *EnclosingScope = nullptr);

void MaybeParseHLSLAnnotations(Declarator &D,
SourceLocation *EndLoc = nullptr) {
SourceLocation *EndLoc = nullptr,
bool CouldBeBitField = false) {
assert(getLangOpts().HLSL && "MaybeParseHLSLAnnotations is for HLSL only");
if (Tok.is(tok::colon)) {
ParsedAttributes Attrs(AttrFactory);
ParseHLSLAnnotations(Attrs, EndLoc);
ParseHLSLAnnotations(Attrs, EndLoc, CouldBeBitField);
D.takeAttributes(Attrs);
}
}

void MaybeParseHLSLAnnotations(ParsedAttributes &Attrs,
SourceLocation *EndLoc = nullptr) {
assert(getLangOpts().HLSL && "MaybeParseHLSLAnnotations is for HLSL only");
if (getLangOpts().HLSL && Tok.is(tok::colon))
if (Tok.is(tok::colon))
ParseHLSLAnnotations(Attrs, EndLoc);
}

void ParseHLSLAnnotations(ParsedAttributes &Attrs,
SourceLocation *EndLoc = nullptr);
SourceLocation *EndLoc = nullptr,
bool CouldBeBitField = false);
Decl *ParseHLSLBuffer(SourceLocation &DeclEnd);

void MaybeParseMicrosoftAttributes(ParsedAttributes &Attrs) {
Expand Down Expand Up @@ -3511,6 +3513,19 @@ class Parser : public CodeCompletionHandler {
/// metadirective and therefore ends on the closing paren.
StmtResult ParseOpenMPDeclarativeOrExecutableDirective(
ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective = false);

/// Parses executable directive.
///
/// \param StmtCtx The context in which we're parsing the directive.
/// \param DKind The kind of the executable directive.
/// \param Loc Source location of the beginning of the directive.
/// \param ReadDirectiveWithinMetadirective true if directive is within a
/// metadirective and therefore ends on the closing paren.
StmtResult
ParseOpenMPExecutableDirective(ParsedStmtContext StmtCtx,
OpenMPDirectiveKind DKind, SourceLocation Loc,
bool ReadDirectiveWithinMetadirective);

/// Parses clause of kind \a CKind for directive of a kind \a Kind.
///
/// \param DKind Kind of current directive.
Expand Down
19 changes: 12 additions & 7 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -2114,8 +2114,6 @@ class Sema final : public SemaBase {

bool FormatStringHasSArg(const StringLiteral *FExpr);

static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);

void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
BinaryOperatorKind Opcode);

Expand Down Expand Up @@ -2228,8 +2226,6 @@ class Sema final : public SemaBase {
bool BuiltinVectorMath(CallExpr *TheCall, QualType &Res);
bool BuiltinVectorToScalarMath(CallExpr *TheCall);

bool CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);

void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
const Expr *ThisArg, ArrayRef<const Expr *> Args,
bool IsMemberFunction, SourceLocation Loc, SourceRange Range,
Expand Down Expand Up @@ -2259,6 +2255,14 @@ class Sema final : public SemaBase {

bool ValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);

void CheckImplicitConversion(Expr *E, QualType T, SourceLocation CC,
bool *ICContext = nullptr,
bool IsListInit = false);

bool BuiltinElementwiseTernaryMath(CallExpr *TheCall,
bool CheckForFloatArgs = true);
bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall);

private:
void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
const ArraySubscriptExpr *ASE = nullptr,
Expand Down Expand Up @@ -2306,9 +2310,6 @@ class Sema final : public SemaBase {
AtomicExpr::AtomicOp Op);

bool BuiltinElementwiseMath(CallExpr *TheCall);
bool BuiltinElementwiseTernaryMath(CallExpr *TheCall,
bool CheckForFloatArgs = true);
bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall);
bool PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall);

bool BuiltinNonDeterministicValue(CallExpr *TheCall);
Expand Down Expand Up @@ -4566,6 +4567,10 @@ class Sema final : public SemaBase {
/// conditions that are needed for the attribute to have an effect.
void checkIllFormedTrivialABIStruct(CXXRecordDecl &RD);

/// Check that VTable Pointer authentication is only being set on the first
/// first instantiation of the vtable
void checkIncorrectVTablePointerAuthenticationAttribute(CXXRecordDecl &RD);

void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc,
Decl *TagDecl, SourceLocation LBrac,
SourceLocation RBrac,
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Sema/SemaHLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class SemaHLSL : public SemaBase {
void handleShaderAttr(Decl *D, const ParsedAttr &AL);
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL);

bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
};

} // namespace clang
Expand Down
21 changes: 21 additions & 0 deletions clang/include/clang/Sema/SemaObjC.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,27 @@ class SemaObjC : public SemaBase {

IdentifierInfo *getNSErrorIdent();

bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);

/// Diagnose use of %s directive in an NSString which is being passed
/// as formatting string to formatting method.
void DiagnoseCStringFormatDirectiveInCFAPI(const NamedDecl *FDecl,
Expr **Args, unsigned NumArgs);

bool isSignedCharBool(QualType Ty);

void adornBoolConversionDiagWithTernaryFixit(
Expr *SourceExpr, const Sema::SemaDiagnosticBuilder &Builder);

/// Check an Objective-C dictionary literal being converted to the given
/// target type.
void checkDictionaryLiteral(QualType TargetType,
ObjCDictionaryLiteral *DictionaryLiteral);

/// Check an Objective-C array literal being converted to the given
/// target type.
void checkArrayLiteral(QualType TargetType, ObjCArrayLiteral *ArrayLiteral);

private:
IdentifierInfo *Ident_NSError = nullptr;

Expand Down
72 changes: 72 additions & 0 deletions clang/include/clang/Sema/SemaOpenCL.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,78 @@ class SemaOpenCL : public SemaBase {

// Handles intel_reqd_sub_group_size.
void handleSubGroupSize(Decl *D, const ParsedAttr &AL);

// Performs semantic analysis for the read/write_pipe call.
// \param S Reference to the semantic analyzer.
// \param Call A pointer to the builtin call.
// \return True if a semantic error has been found, false otherwise.
bool checkBuiltinRWPipe(CallExpr *Call);

// Performs a semantic analysis on the {work_group_/sub_group_
// /_}reserve_{read/write}_pipe
// \param S Reference to the semantic analyzer.
// \param Call The call to the builtin function to be analyzed.
// \return True if a semantic error was found, false otherwise.
bool checkBuiltinReserveRWPipe(CallExpr *Call);

bool checkSubgroupExt(CallExpr *Call);

// Performs a semantic analysis on {work_group_/sub_group_
// /_}commit_{read/write}_pipe
// \param S Reference to the semantic analyzer.
// \param Call The call to the builtin function to be analyzed.
// \return True if a semantic error was found, false otherwise.
bool checkBuiltinCommitRWPipe(CallExpr *Call);

// Performs a semantic analysis on the call to built-in Pipe
// Query Functions.
// \param S Reference to the semantic analyzer.
// \param Call The call to the builtin function to be analyzed.
// \return True if a semantic error was found, false otherwise.
bool checkBuiltinPipePackets(CallExpr *Call);

// OpenCL v2.0 s6.13.9 - Address space qualifier functions.
// Performs semantic analysis for the to_global/local/private call.
// \param S Reference to the semantic analyzer.
// \param BuiltinID ID of the builtin function.
// \param Call A pointer to the builtin call.
// \return True if a semantic error has been found, false otherwise.
bool checkBuiltinToAddr(unsigned BuiltinID, CallExpr *Call);

/// OpenCL C v2.0, s6.13.17 - Enqueue kernel function contains four different
/// overload formats specified in Table 6.13.17.1.
/// int enqueue_kernel(queue_t queue,
/// kernel_enqueue_flags_t flags,
/// const ndrange_t ndrange,
/// void (^block)(void))
/// int enqueue_kernel(queue_t queue,
/// kernel_enqueue_flags_t flags,
/// const ndrange_t ndrange,
/// uint num_events_in_wait_list,
/// clk_event_t *event_wait_list,
/// clk_event_t *event_ret,
/// void (^block)(void))
/// int enqueue_kernel(queue_t queue,
/// kernel_enqueue_flags_t flags,
/// const ndrange_t ndrange,
/// void (^block)(local void*, ...),
/// uint size0, ...)
/// int enqueue_kernel(queue_t queue,
/// kernel_enqueue_flags_t flags,
/// const ndrange_t ndrange,
/// uint num_events_in_wait_list,
/// clk_event_t *event_wait_list,
/// clk_event_t *event_ret,
/// void (^block)(local void*, ...),
/// uint size0, ...)
bool checkBuiltinEnqueueKernel(CallExpr *TheCall);

/// OpenCL C v2.0, s6.13.17.6 - Check the argument to the
/// get_kernel_work_group_size
/// and get_kernel_preferred_work_group_size_multiple builtin functions.
bool checkBuiltinKernelWorkGroupSize(CallExpr *TheCall);

bool checkBuiltinNDRangeAndBlock(CallExpr *TheCall);
};

} // namespace clang
Expand Down
21 changes: 5 additions & 16 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -686,22 +686,11 @@ def MoveChecker: Checker<"Move">,
CheckerOptions<[
CmdLineOption<String,
"WarnOn",
"In non-aggressive mode, only warn on use-after-move of "
"local variables (or local rvalue references) and of STL "
"objects. The former is possible because local variables (or "
"local rvalue references) are not tempting their user to "
"re-use the storage. The latter is possible because STL "
"objects are known to end up in a valid but unspecified "
"state after the move and their state-reset methods are also "
"known, which allows us to predict precisely when "
"use-after-move is invalid. Some STL objects are known to "
"conform to additional contracts after move, so they are not "
"tracked. However, smart pointers specifically are tracked "
"because we can perform extra checking over them. In "
"aggressive mode, warn on any use-after-move because the "
"user has intentionally asked us to completely eliminate "
"use-after-move in his code. Values: \"KnownsOnly\", "
"\"KnownsAndLocals\", \"All\".",
"With setting \"KnownsOnly\" warn only on objects with known "
"move semantics like smart pointers and other STL objects. "
"With setting \"KnownsAndLocals\" warn additionally on local "
"variables (or rvalue references). With setting \"All\" warn "
"on all variables (excluding global variables).",
"KnownsAndLocals",
Released>
]>,
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Tooling/Transformer/RangeSelector.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ RangeSelector name(std::string ID);
// source between the call's parentheses).
RangeSelector callArgs(std::string ID);

// Given a \c CXXConstructExpr (bound to \p ID), selects the
// arguments' source text. Depending on the syntactic form of the construct,
// this is the range between parentheses or braces.
RangeSelector constructExprArgs(std::string ID);

// Given a \c CompoundStmt (bound to \p ID), selects the source of the
// statements (all source between the braces).
RangeSelector statements(std::string ID);
Expand Down
16 changes: 9 additions & 7 deletions clang/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,20 @@ module Clang_Basic {
umbrella "clang/Basic"

textual header "clang/Basic/AArch64SVEACLETypes.def"
textual header "clang/Basic/AMDGPUTypes.def"
textual header "clang/Basic/BuiltinHeaders.def"
textual header "clang/Basic/BuiltinsAArch64.def"
textual header "clang/Basic/BuiltinsAMDGPU.def"
textual header "clang/Basic/BuiltinsAArch64NeonSVEBridge.def"
textual header "clang/Basic/BuiltinsAArch64NeonSVEBridge_cg.def"
textual header "clang/Basic/BuiltinsAMDGPU.def"
textual header "clang/Basic/BuiltinsARM.def"
textual header "clang/Basic/BuiltinHeaders.def"
textual header "clang/Basic/BuiltinsHexagon.def"
textual header "clang/Basic/BuiltinsHexagonDep.def"
textual header "clang/Basic/BuiltinsHexagonMapCustomDep.def"
textual header "clang/Basic/BuiltinsLoongArch.def"
textual header "clang/Basic/BuiltinsLoongArchBase.def"
textual header "clang/Basic/BuiltinsLoongArchLSX.def"
textual header "clang/Basic/BuiltinsLoongArchLASX.def"
textual header "clang/Basic/BuiltinsLoongArchLSX.def"
textual header "clang/Basic/BuiltinsMips.def"
textual header "clang/Basic/BuiltinsNEON.def"
textual header "clang/Basic/BuiltinsNVPTX.def"
Expand All @@ -67,22 +68,23 @@ module Clang_Basic {
textual header "clang/Basic/CodeGenOptions.def"
textual header "clang/Basic/DebugOptions.def"
textual header "clang/Basic/DiagnosticOptions.def"
textual header "clang/Basic/Features.def"
textual header "clang/Basic/FPOptions.def"
textual header "clang/Basic/MSP430Target.def"
textual header "clang/Basic/Features.def"
textual header "clang/Basic/LangOptions.def"
textual header "clang/Basic/MSP430Target.def"
textual header "clang/Basic/OpenACCClauses.def"
textual header "clang/Basic/OpenCLExtensionTypes.def"
textual header "clang/Basic/OpenCLExtensions.def"
textual header "clang/Basic/OpenCLImageTypes.def"
textual header "clang/Basic/OpenCLExtensionTypes.def"
textual header "clang/Basic/OpenMPKinds.def"
textual header "clang/Basic/OperatorKinds.def"
textual header "clang/Basic/PPCTypes.def"
textual header "clang/Basic/RISCVVTypes.def"
textual header "clang/Basic/Sanitizers.def"
textual header "clang/Basic/TargetCXXABI.def"
textual header "clang/Basic/TargetOSMacros.def"
textual header "clang/Basic/TransformTypeTraits.def"
textual header "clang/Basic/TokenKinds.def"
textual header "clang/Basic/TransformTypeTraits.def"
textual header "clang/Basic/WebAssemblyReferenceTypes.def"

module * { export * }
Expand Down
83 changes: 83 additions & 0 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SipHash.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/AArch64TargetParser.h"
#include "llvm/TargetParser/Triple.h"
Expand Down Expand Up @@ -3128,6 +3129,17 @@ QualType ASTContext::removeAddrSpaceQualType(QualType T) const {
return QualType(TypeNode, Quals.getFastQualifiers());
}

uint16_t
ASTContext::getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD) {
assert(RD->isPolymorphic() &&
"Attempted to get vtable pointer discriminator on a monomorphic type");
std::unique_ptr<MangleContext> MC(createMangleContext());
SmallString<256> Str;
llvm::raw_svector_ostream Out(Str);
MC->mangleCXXVTable(RD, Out);
return llvm::getPointerAuthStableSipHash(Str);
}

QualType ASTContext::getObjCGCQualType(QualType T,
Qualifiers::GC GCAttr) const {
QualType CanT = getCanonicalType(T);
Expand Down Expand Up @@ -13894,3 +13906,74 @@ StringRef ASTContext::getCUIDHash() const {
CUIDHash = llvm::utohexstr(llvm::MD5Hash(LangOpts.CUID), /*LowerCase=*/true);
return CUIDHash;
}

const CXXRecordDecl *
ASTContext::baseForVTableAuthentication(const CXXRecordDecl *ThisClass) {
assert(ThisClass);
assert(ThisClass->isPolymorphic());
const CXXRecordDecl *PrimaryBase = ThisClass;
while (1) {
assert(PrimaryBase);
assert(PrimaryBase->isPolymorphic());
auto &Layout = getASTRecordLayout(PrimaryBase);
auto Base = Layout.getPrimaryBase();
if (!Base || Base == PrimaryBase || !Base->isPolymorphic())
break;
PrimaryBase = Base;
}
return PrimaryBase;
}

bool ASTContext::useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
StringRef MangledName) {
auto *Method = cast<CXXMethodDecl>(VirtualMethodDecl.getDecl());
assert(Method->isVirtual());
bool DefaultIncludesPointerAuth =
LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics;

if (!DefaultIncludesPointerAuth)
return true;

auto Existing = ThunksToBeAbbreviated.find(VirtualMethodDecl);
if (Existing != ThunksToBeAbbreviated.end())
return Existing->second.contains(MangledName.str());

std::unique_ptr<MangleContext> Mangler(createMangleContext());
llvm::StringMap<llvm::SmallVector<std::string, 2>> Thunks;
auto VtableContext = getVTableContext();
if (const auto *ThunkInfos = VtableContext->getThunkInfo(VirtualMethodDecl)) {
auto *Destructor = dyn_cast<CXXDestructorDecl>(Method);
for (const auto &Thunk : *ThunkInfos) {
SmallString<256> ElidedName;
llvm::raw_svector_ostream ElidedNameStream(ElidedName);
if (Destructor)
Mangler->mangleCXXDtorThunk(Destructor, VirtualMethodDecl.getDtorType(),
Thunk, /* elideOverrideInfo */ true,
ElidedNameStream);
else
Mangler->mangleThunk(Method, Thunk, /* elideOverrideInfo */ true,
ElidedNameStream);
SmallString<256> MangledName;
llvm::raw_svector_ostream mangledNameStream(MangledName);
if (Destructor)
Mangler->mangleCXXDtorThunk(Destructor, VirtualMethodDecl.getDtorType(),
Thunk, /* elideOverrideInfo */ false,
mangledNameStream);
else
Mangler->mangleThunk(Method, Thunk, /* elideOverrideInfo */ false,
mangledNameStream);

if (Thunks.find(ElidedName) == Thunks.end())
Thunks[ElidedName] = {};
Thunks[ElidedName].push_back(std::string(MangledName));
}
}
llvm::StringSet<> SimplifiedThunkNames;
for (auto &ThunkList : Thunks) {
llvm::sort(ThunkList.second);
SimplifiedThunkNames.insert(ThunkList.second[0]);
}
bool Result = SimplifiedThunkNames.contains(MangledName);
ThunksToBeAbbreviated[VirtualMethodDecl] = std::move(SimplifiedThunkNames);
return Result;
}
3 changes: 1 addition & 2 deletions clang/lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,7 @@ LLVM_DUMP_METHOD void APValue::dump() const {

LLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,
const ASTContext &Context) const {
ASTDumper Dumper(llvm::errs(), Context,
Context.getDiagnostics().getShowColors());
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));
}

Expand Down
3 changes: 1 addition & 2 deletions clang/lib/AST/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ add_clang_library(clangAST
FormatString.cpp
InheritViz.cpp
Interp/ByteCodeEmitter.cpp
Interp/ByteCodeExprGen.cpp
Interp/ByteCodeStmtGen.cpp
Interp/Compiler.cpp
Interp/Context.cpp
Interp/Descriptor.cpp
Interp/Disasm.cpp
Expand Down
23 changes: 4 additions & 19 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1614,7 +1614,7 @@ LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) {
: CK);
}

Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const {
Module *Decl::getOwningModuleForLinkage() const {
if (isa<NamespaceDecl>(this))
// Namespaces never have module linkage. It is the entities within them
// that [may] do.
Expand All @@ -1637,24 +1637,9 @@ Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const {

case Module::ModuleHeaderUnit:
case Module::ExplicitGlobalModuleFragment:
case Module::ImplicitGlobalModuleFragment: {
// External linkage declarations in the global module have no owning module
// for linkage purposes. But internal linkage declarations in the global
// module fragment of a particular module are owned by that module for
// linkage purposes.
// FIXME: p1815 removes the need for this distinction -- there are no
// internal linkage declarations that need to be referred to from outside
// this TU.
if (IgnoreLinkage)
return nullptr;
bool InternalLinkage;
if (auto *ND = dyn_cast<NamedDecl>(this))
InternalLinkage = !ND->hasExternalFormalLinkage();
else
InternalLinkage = isInAnonymousNamespace();
return InternalLinkage ? M->Kind == Module::ModuleHeaderUnit ? M : M->Parent
: nullptr;
}
case Module::ImplicitGlobalModuleFragment:
// The global module shouldn't change the linkage.
return nullptr;

case Module::PrivateModuleFragment:
// The private module fragment is part of its containing module for linkage
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/AST/DeclPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,13 @@ void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params,
}

Out << '>';

if (const Expr *RequiresClause = Params->getRequiresClause()) {
Out << " requires ";
RequiresClause->printPretty(Out, nullptr, Policy, Indentation, "\n",
&Context);
}

if (!OmitTemplateKW)
Out << ' ';
}
Expand Down
21 changes: 18 additions & 3 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1885,7 +1885,8 @@ static bool EvaluateAtomic(const Expr *E, const LValue *This, APValue &Result,
EvalInfo &Info);
static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result);
static bool EvaluateBuiltinStrLen(const Expr *E, uint64_t &Result,
EvalInfo &Info);
EvalInfo &Info,
std::string *StringResult = nullptr);

/// Evaluate an integer or fixed point expression into an APResult.
static bool EvaluateFixedPointOrInteger(const Expr *E, APFixedPoint &Result,
Expand Down Expand Up @@ -17009,7 +17010,7 @@ bool Expr::tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
}

static bool EvaluateBuiltinStrLen(const Expr *E, uint64_t &Result,
EvalInfo &Info) {
EvalInfo &Info, std::string *StringResult) {
if (!E->getType()->hasPointerRepresentation() || !E->isPRValue())
return false;

Expand All @@ -17036,6 +17037,8 @@ static bool EvaluateBuiltinStrLen(const Expr *E, uint64_t &Result,
Str = Str.substr(0, Pos);

Result = Str.size();
if (StringResult)
*StringResult = Str;
return true;
}

Expand All @@ -17051,12 +17054,24 @@ static bool EvaluateBuiltinStrLen(const Expr *E, uint64_t &Result,
if (!Char.getInt()) {
Result = Strlen;
return true;
}
} else if (StringResult)
StringResult->push_back(Char.getInt().getExtValue());
if (!HandleLValueArrayAdjustment(Info, E, String, CharTy, 1))
return false;
}
}

std::optional<std::string> Expr::tryEvaluateString(ASTContext &Ctx) const {
Expr::EvalStatus Status;
EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold);
uint64_t Result;
std::string StringResult;

if (EvaluateBuiltinStrLen(this, Result, Info, &StringResult))
return StringResult;
return {};
}

bool Expr::EvaluateCharRangeAsString(std::string &Result,
const Expr *SizeExpression,
const Expr *PtrExpression, ASTContext &Ctx,
Expand Down
734 changes: 0 additions & 734 deletions clang/lib/AST/Interp/ByteCodeStmtGen.cpp

This file was deleted.

91 changes: 0 additions & 91 deletions clang/lib/AST/Interp/ByteCodeStmtGen.h

This file was deleted.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===--- ByteCodeExprGen.h - Code generator for expressions -----*- C++ -*-===//
//===--- Compiler.h - Code generator for expressions -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand Down Expand Up @@ -36,8 +36,11 @@ template <class Emitter> class InitLinkScope;
template <class Emitter> class OptionScope;
template <class Emitter> class ArrayIndexScope;
template <class Emitter> class SourceLocScope;
template <class Emitter> class LoopScope;
template <class Emitter> class LabelScope;
template <class Emitter> class SwitchScope;

template <class Emitter> class ByteCodeExprGen;
template <class Emitter> class Compiler;
struct InitLink {
public:
enum {
Expand All @@ -60,7 +63,7 @@ struct InitLink {

InitLink(uint8_t Kind) : Kind(Kind) {}
template <class Emitter>
bool emit(ByteCodeExprGen<Emitter> *Ctx, const Expr *E) const;
bool emit(Compiler<Emitter> *Ctx, const Expr *E) const;

private:
uint32_t Kind;
Expand All @@ -84,12 +87,14 @@ struct VarCreationState {

/// Compilation context for expressions.
template <class Emitter>
class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
public Emitter {
class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
public Emitter {
protected:
// Aliases for types defined in the emitter.
using LabelTy = typename Emitter::LabelTy;
using AddrTy = typename Emitter::AddrTy;
using OptLabelTy = std::optional<LabelTy>;
using CaseMap = llvm::DenseMap<const SwitchCase *, LabelTy>;

/// Current compilation context.
Context &Ctx;
Expand All @@ -99,10 +104,10 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
public:
/// Initializes the compiler and the backend emitter.
template <typename... Tys>
ByteCodeExprGen(Context &Ctx, Program &P, Tys &&... Args)
Compiler(Context &Ctx, Program &P, Tys &&...Args)
: Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {}

// Expression visitors - result returned on interp stack.
// Expressions.
bool VisitCastExpr(const CastExpr *E);
bool VisitIntegerLiteral(const IntegerLiteral *E);
bool VisitFloatingLiteral(const FloatingLiteral *E);
Expand Down Expand Up @@ -177,10 +182,31 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E);
bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E);
bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E);

// Statements.
bool visitCompoundStmt(const CompoundStmt *S);
bool visitLoopBody(const Stmt *S);
bool visitDeclStmt(const DeclStmt *DS);
bool visitReturnStmt(const ReturnStmt *RS);
bool visitIfStmt(const IfStmt *IS);
bool visitWhileStmt(const WhileStmt *S);
bool visitDoStmt(const DoStmt *S);
bool visitForStmt(const ForStmt *S);
bool visitCXXForRangeStmt(const CXXForRangeStmt *S);
bool visitBreakStmt(const BreakStmt *S);
bool visitContinueStmt(const ContinueStmt *S);
bool visitSwitchStmt(const SwitchStmt *S);
bool visitCaseStmt(const CaseStmt *S);
bool visitDefaultStmt(const DefaultStmt *S);
bool visitAttributedStmt(const AttributedStmt *S);
bool visitCXXTryStmt(const CXXTryStmt *S);

protected:
bool visitStmt(const Stmt *S);
bool visitExpr(const Expr *E) override;
bool visitDecl(const VarDecl *VD, bool ConstantContext) override;
bool visitFunc(const FunctionDecl *F) override;

protected:
/// Emits scope cleanup instructions.
Expand All @@ -193,8 +219,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
Record *getRecord(QualType Ty);
Record *getRecord(const RecordDecl *RD);

// Returns a function for the given FunctionDecl.
// If the function does not exist yet, it is compiled.
/// Returns a function for the given FunctionDecl.
/// If the function does not exist yet, it is compiled.
const Function *getFunction(const FunctionDecl *FD);

std::optional<PrimType> classify(const Expr *E) const {
Expand Down Expand Up @@ -304,6 +330,9 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
friend class ArrayIndexScope<Emitter>;
friend class SourceLocScope<Emitter>;
friend struct InitLink;
friend class LoopScope<Emitter>;
friend class LabelScope<Emitter>;
friend class SwitchScope<Emitter>;

/// Emits a zero initializer.
bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E);
Expand Down Expand Up @@ -347,6 +376,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool emitDestruction(const Descriptor *Desc);
unsigned collectBaseOffset(const QualType BaseType,
const QualType DerivedType);
bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);

protected:
/// Variable to storage mapping.
Expand Down Expand Up @@ -377,15 +407,28 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,

/// Flag indicating if we're initializing a global variable.
bool GlobalDecl = false;

/// Type of the expression returned by the function.
std::optional<PrimType> ReturnType;

/// Switch case mapping.
CaseMap CaseLabels;

/// Point to break to.
OptLabelTy BreakLabel;
/// Point to continue to.
OptLabelTy ContinueLabel;
/// Default case label.
OptLabelTy DefaultLabel;
};

extern template class ByteCodeExprGen<ByteCodeEmitter>;
extern template class ByteCodeExprGen<EvalEmitter>;
extern template class Compiler<ByteCodeEmitter>;
extern template class Compiler<EvalEmitter>;

/// Scope chain managing the variable lifetimes.
template <class Emitter> class VariableScope {
public:
VariableScope(ByteCodeExprGen<Emitter> *Ctx, const ValueDecl *VD)
VariableScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)
: Ctx(Ctx), Parent(Ctx->VarScope), ValDecl(VD) {
Ctx->VarScope = this;
}
Expand Down Expand Up @@ -432,8 +475,8 @@ template <class Emitter> class VariableScope {
VariableScope *getParent() const { return Parent; }

protected:
/// ByteCodeExprGen instance.
ByteCodeExprGen<Emitter> *Ctx;
/// Compiler instance.
Compiler<Emitter> *Ctx;
/// Link to the parent scope.
VariableScope *Parent;
const ValueDecl *ValDecl = nullptr;
Expand All @@ -442,8 +485,7 @@ template <class Emitter> class VariableScope {
/// Generic scope for local variables.
template <class Emitter> class LocalScope : public VariableScope<Emitter> {
public:
LocalScope(ByteCodeExprGen<Emitter> *Ctx)
: VariableScope<Emitter>(Ctx, nullptr) {}
LocalScope(Compiler<Emitter> *Ctx) : VariableScope<Emitter>(Ctx, nullptr) {}

/// Emit a Destroy op for this scope.
~LocalScope() override {
Expand Down Expand Up @@ -537,8 +579,7 @@ template <class Emitter> class DestructorScope final {
/// variables are automatically emitted when the AutoScope is destroyed.
template <class Emitter> class AutoScope : public LocalScope<Emitter> {
public:
AutoScope(ByteCodeExprGen<Emitter> *Ctx)
: LocalScope<Emitter>(Ctx), DS(*this) {}
AutoScope(Compiler<Emitter> *Ctx) : LocalScope<Emitter>(Ctx), DS(*this) {}

private:
DestructorScope<Emitter> DS;
Expand All @@ -547,7 +588,7 @@ template <class Emitter> class AutoScope : public LocalScope<Emitter> {
/// Scope for storage declared in a compound statement.
template <class Emitter> class BlockScope final : public AutoScope<Emitter> {
public:
BlockScope(ByteCodeExprGen<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}
BlockScope(Compiler<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}

void addExtended(const Scope::Local &Local) override {
// If we to this point, just add the variable as a normal local
Expand All @@ -559,27 +600,26 @@ template <class Emitter> class BlockScope final : public AutoScope<Emitter> {

template <class Emitter> class ExprScope final : public AutoScope<Emitter> {
public:
ExprScope(ByteCodeExprGen<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}
ExprScope(Compiler<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}
};

template <class Emitter> class ArrayIndexScope final {
public:
ArrayIndexScope(ByteCodeExprGen<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
ArrayIndexScope(Compiler<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
OldArrayIndex = Ctx->ArrayIndex;
Ctx->ArrayIndex = Index;
}

~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; }

private:
ByteCodeExprGen<Emitter> *Ctx;
Compiler<Emitter> *Ctx;
std::optional<uint64_t> OldArrayIndex;
};

template <class Emitter> class SourceLocScope final {
public:
SourceLocScope(ByteCodeExprGen<Emitter> *Ctx, const Expr *DefaultExpr)
: Ctx(Ctx) {
SourceLocScope(Compiler<Emitter> *Ctx, const Expr *DefaultExpr) : Ctx(Ctx) {
assert(DefaultExpr);
// We only switch if the current SourceLocDefaultExpr is null.
if (!Ctx->SourceLocDefaultExpr) {
Expand All @@ -594,20 +634,20 @@ template <class Emitter> class SourceLocScope final {
}

private:
ByteCodeExprGen<Emitter> *Ctx;
Compiler<Emitter> *Ctx;
bool Enabled = false;
};

template <class Emitter> class InitLinkScope final {
public:
InitLinkScope(ByteCodeExprGen<Emitter> *Ctx, InitLink &&Link) : Ctx(Ctx) {
InitLinkScope(Compiler<Emitter> *Ctx, InitLink &&Link) : Ctx(Ctx) {
Ctx->InitStack.push_back(std::move(Link));
}

~InitLinkScope() { this->Ctx->InitStack.pop_back(); }

private:
ByteCodeExprGen<Emitter> *Ctx;
Compiler<Emitter> *Ctx;
};

} // namespace interp
Expand Down
13 changes: 6 additions & 7 deletions clang/lib/AST/Interp/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@

#include "Context.h"
#include "ByteCodeEmitter.h"
#include "ByteCodeExprGen.h"
#include "ByteCodeStmtGen.h"
#include "Compiler.h"
#include "EvalEmitter.h"
#include "Interp.h"
#include "InterpFrame.h"
Expand All @@ -30,7 +29,7 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
assert(Stk.empty());
Function *Func = P->getFunction(FD);
if (!Func || !Func->hasBody())
Func = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD);
Func = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD);

APValue DummyResult;
if (!Run(Parent, Func, DummyResult))
Expand All @@ -41,7 +40,7 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {

bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
bool Recursing = !Stk.empty();
ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk);
Compiler<EvalEmitter> C(*this, *P, Parent, Stk);

auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue());

Expand All @@ -67,7 +66,7 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {

bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {
bool Recursing = !Stk.empty();
ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk);
Compiler<EvalEmitter> C(*this, *P, Parent, Stk);

auto Res = C.interpretExpr(E);
if (Res.isInvalid()) {
Expand All @@ -92,7 +91,7 @@ bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {
bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
APValue &Result) {
bool Recursing = !Stk.empty();
ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk);
Compiler<EvalEmitter> C(*this, *P, Parent, Stk);

bool CheckGlobalInitialized =
shouldBeGloballyIndexed(VD) &&
Expand Down Expand Up @@ -261,7 +260,7 @@ const Function *Context::getOrCreateFunction(const FunctionDecl *FD) {
return Func;

if (!Func || WasNotDefined) {
if (auto F = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD))
if (auto F = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD))
Func = F;
}

Expand Down
9 changes: 8 additions & 1 deletion clang/lib/AST/Interp/Descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,14 @@ static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D) {
template <typename T>
static void moveArrayTy(Block *, const std::byte *Src, std::byte *Dst,
const Descriptor *D) {
// FIXME: Need to copy the InitMap?
// FIXME: Get rid of the const_cast.
InitMapPtr &SrcIMP =
*reinterpret_cast<InitMapPtr *>(const_cast<std::byte *>(Src));
if (SrcIMP) {
// We only ever invoke the moveFunc when moving block contents to a
// DeadBlock. DeadBlocks don't need InitMaps, so we destroy them here.
SrcIMP = std::nullopt;
}
Src += sizeof(InitMapPtr);
Dst += sizeof(InitMapPtr);
for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/AST/Interp/Disasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "Program.h"
#include "clang/AST/ASTDumperUtils.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Format.h"

Expand Down Expand Up @@ -154,6 +155,19 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
OS << (GP.isInitialized() ? "initialized " : "uninitialized ");
}
Desc->dump(OS);

if (Desc->IsTemporary) {
if (const auto *MTE =
dyn_cast_if_present<MaterializeTemporaryExpr>(Desc->asExpr());
MTE && MTE->getLifetimeExtendedTemporaryDecl()) {
const APValue *V = MTE->getLifetimeExtendedTemporaryDecl()->getValue();
if (V->isInt())
OS << " (global temporary value: " << V->getInt() << ")";
else
OS << " (huh?)";
}
}

OS << "\n";
if (GP.isInitialized() && Desc->isPrimitive() && !Desc->isDummy()) {
OS << " ";
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/Interp/EvalEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ EvaluationResult EvalEmitter::interpretExpr(const Expr *E,
EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
bool CheckFullyInitialized) {
this->CheckFullyInitialized = CheckFullyInitialized;
S.EvaluatingDecl = VD;

if (const Expr *Init = VD->getAnyInitializer()) {
QualType T = VD->getType();
Expand All @@ -69,6 +70,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
if (!this->visitDecl(VD, S.inConstantContext()) && EvalResult.empty())
EvalResult.setInvalid();

S.EvaluatingDecl = nullptr;
return std::move(this->EvalResult);
}

Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/EvalEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class EvalEmitter : public SourceMapper {
/// Methods implemented by the compiler.
virtual bool visitExpr(const Expr *E) = 0;
virtual bool visitDecl(const VarDecl *VD, bool ConstantContext) = 0;
virtual bool visitFunc(const FunctionDecl *F) = 0;

/// Emits jumps.
bool jumpTrue(const LabelTy &Label);
Expand Down
15 changes: 10 additions & 5 deletions clang/lib/AST/Interp/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
};

if (const auto *D = Desc->asVarDecl();
D && D->hasGlobalStorage() && !IsConstType(D)) {
D && D->hasGlobalStorage() && D != S.EvaluatingDecl && !IsConstType(D)) {
diagnoseNonConstVariable(S, OpPC, D);
return S.inConstantContext();
}
Expand All @@ -341,7 +341,9 @@ bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
if (!Ptr.isZero())
return true;
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_null_subobject) << CSK;
S.FFDiag(Loc, diag::note_constexpr_null_subobject)
<< CSK << S.Current->getRange(OpPC);

return false;
}

Expand All @@ -350,7 +352,8 @@ bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
if (!Ptr.isOnePastEnd())
return true;
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_access_past_end) << AK;
S.FFDiag(Loc, diag::note_constexpr_access_past_end)
<< AK << S.Current->getRange(OpPC);
return false;
}

Expand All @@ -359,7 +362,8 @@ bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
if (!Ptr.isElementPastEnd())
return true;
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
<< CSK << S.Current->getRange(OpPC);
return false;
}

Expand All @@ -369,7 +373,8 @@ bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return true;

const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_past_end_subobject) << CSK;
S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
<< CSK << S.Current->getRange(OpPC);
return false;
}

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/Interp/InterpState.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ class InterpState final : public State, public SourceMapper {
InterpFrame *Current = nullptr;
/// Source location of the evaluating expression
SourceLocation EvalLocation;
/// Declaration we're initializing/evaluting, if any.
const VarDecl *EvaluatingDecl = nullptr;
};

} // namespace interp
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx) const {
Ty = AT->getValueType();

// Invalid pointers.
if (Ptr.isDummy() || !Ptr.isLive() ||
if (Ptr.isDummy() || !Ptr.isLive() || !Ptr.isBlockPointer() ||
(!Ptr.isUnknownSizeArray() && Ptr.isOnePastEnd()))
return false;

Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/Interp/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,8 @@ class Pointer {
unsigned getByteOffset() const {
if (isIntegralPointer())
return asIntPointer().Value + Offset;
if (isOnePastEnd())
return PastEndMark;
return Offset;
}

Expand Down Expand Up @@ -551,6 +553,9 @@ class Pointer {
if (!asBlockPointer().Pointee)
return false;

if (isUnknownSizeArray())
return false;

return isElementPastEnd() ||
(getSize() == getOffset() && !isZeroSizeArray());
}
Expand Down
1 change: 0 additions & 1 deletion clang/lib/AST/Interp/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//

#include "Program.h"
#include "ByteCodeStmtGen.h"
#include "Context.h"
#include "Function.h"
#include "Integral.h"
Expand Down
90 changes: 83 additions & 7 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,10 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
}

void mangleCXXName(GlobalDecl GD, raw_ostream &) override;
void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, bool,
raw_ostream &) override;
void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &ThisAdjustment,
raw_ostream &) override;
const ThunkInfo &Thunk, bool, raw_ostream &) override;
void mangleReferenceTemporary(const VarDecl *D, unsigned ManglingNumber,
raw_ostream &) override;
void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) override;
Expand Down Expand Up @@ -468,6 +467,7 @@ class CXXNameMangler {
void mangleNameOrStandardSubstitution(const NamedDecl *ND);
void mangleLambdaSig(const CXXRecordDecl *Lambda);
void mangleModuleNamePrefix(StringRef Name, bool IsPartition = false);
void mangleVendorQualifier(StringRef Name);

private:

Expand Down Expand Up @@ -559,7 +559,6 @@ class CXXNameMangler {
StringRef Prefix = "");
void mangleOperatorName(DeclarationName Name, unsigned Arity);
void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
void mangleVendorQualifier(StringRef qualifier);
void mangleQualifiers(Qualifiers Quals, const DependentAddressSpaceType *DAST = nullptr);
void mangleRefQualifier(RefQualifierKind RefQualifier);

Expand Down Expand Up @@ -7044,8 +7043,78 @@ void ItaniumMangleContextImpl::mangleCXXDtorComdat(const CXXDestructorDecl *D,
Mangler.mangle(GlobalDecl(D, Dtor_Comdat));
}

/// Mangles the pointer authentication override attribute for classes
/// that have explicit overrides for the vtable authentication schema.
///
/// The override is mangled as a parameterized vendor extension as follows
///
/// <type> ::= U "__vtptrauth" I
/// <key>
/// <addressDiscriminated>
/// <extraDiscriminator>
/// E
///
/// The extra discriminator encodes the explicit value derived from the
/// override schema, e.g. if the override has specified type based
/// discrimination the encoded value will be the discriminator derived from the
/// type name.
static void mangleOverrideDiscrimination(CXXNameMangler &Mangler,
ASTContext &Context,
const ThunkInfo &Thunk) {
auto &LangOpts = Context.getLangOpts();
const CXXRecordDecl *ThisRD = Thunk.ThisType->getPointeeCXXRecordDecl();
const CXXRecordDecl *PtrauthClassRD =
Context.baseForVTableAuthentication(ThisRD);
unsigned TypedDiscriminator =
Context.getPointerAuthVTablePointerDiscriminator(ThisRD);
Mangler.mangleVendorQualifier("__vtptrauth");
auto &ManglerStream = Mangler.getStream();
ManglerStream << "I";
if (const auto *ExplicitAuth =
PtrauthClassRD->getAttr<VTablePointerAuthenticationAttr>()) {
ManglerStream << "Lj" << ExplicitAuth->getKey();

if (ExplicitAuth->getAddressDiscrimination() ==
VTablePointerAuthenticationAttr::DefaultAddressDiscrimination)
ManglerStream << "Lb" << LangOpts.PointerAuthVTPtrAddressDiscrimination;
else
ManglerStream << "Lb"
<< (ExplicitAuth->getAddressDiscrimination() ==
VTablePointerAuthenticationAttr::AddressDiscrimination);

switch (ExplicitAuth->getExtraDiscrimination()) {
case VTablePointerAuthenticationAttr::DefaultExtraDiscrimination: {
if (LangOpts.PointerAuthVTPtrTypeDiscrimination)
ManglerStream << "Lj" << TypedDiscriminator;
else
ManglerStream << "Lj" << 0;
break;
}
case VTablePointerAuthenticationAttr::TypeDiscrimination:
ManglerStream << "Lj" << TypedDiscriminator;
break;
case VTablePointerAuthenticationAttr::CustomDiscrimination:
ManglerStream << "Lj" << ExplicitAuth->getCustomDiscriminationValue();
break;
case VTablePointerAuthenticationAttr::NoExtraDiscrimination:
ManglerStream << "Lj" << 0;
break;
}
} else {
ManglerStream << "Lj"
<< (unsigned)VTablePointerAuthenticationAttr::DefaultKey;
ManglerStream << "Lb" << LangOpts.PointerAuthVTPtrAddressDiscrimination;
if (LangOpts.PointerAuthVTPtrTypeDiscrimination)
ManglerStream << "Lj" << TypedDiscriminator;
else
ManglerStream << "Lj" << 0;
}
ManglerStream << "E";
}

void ItaniumMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
bool ElideOverrideInfo,
raw_ostream &Out) {
// <special-name> ::= T <call-offset> <base encoding>
// # base is the nominal target function of thunk
Expand All @@ -7071,21 +7140,28 @@ void ItaniumMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
Thunk.Return.Virtual.Itanium.VBaseOffsetOffset);

Mangler.mangleFunctionEncoding(MD);
if (!ElideOverrideInfo)
mangleOverrideDiscrimination(Mangler, getASTContext(), Thunk);
}

void ItaniumMangleContextImpl::mangleCXXDtorThunk(
const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &ThisAdjustment, raw_ostream &Out) {
void ItaniumMangleContextImpl::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
CXXDtorType Type,
const ThunkInfo &Thunk,
bool ElideOverrideInfo,
raw_ostream &Out) {
// <special-name> ::= T <call-offset> <base encoding>
// # base is the nominal target function of thunk
CXXNameMangler Mangler(*this, Out, DD, Type);
Mangler.getStream() << "_ZT";

auto &ThisAdjustment = Thunk.This;
// Mangle the 'this' pointer adjustment.
Mangler.mangleCallOffset(ThisAdjustment.NonVirtual,
ThisAdjustment.Virtual.Itanium.VCallOffsetOffset);

Mangler.mangleFunctionEncoding(GlobalDecl(DD, Type));
if (!ElideOverrideInfo)
mangleOverrideDiscrimination(Mangler, getASTContext(), Thunk);
}

/// Returns the mangled name for a guard variable for the passed in VarDecl.
Expand Down
23 changes: 17 additions & 6 deletions clang/lib/AST/Mangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,10 +513,20 @@ class ASTNameGenerator::Implementation {
}
} else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
Manglings.emplace_back(getName(ND));
if (MD->isVirtual())
if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD))
for (const auto &T : *TIV)
Manglings.emplace_back(getMangledThunk(MD, T));
if (MD->isVirtual()) {
if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD)) {
for (const auto &T : *TIV) {
std::string ThunkName;
std::string ContextualizedName =
getMangledThunk(MD, T, /* ElideOverrideInfo */ false);
if (Ctx.useAbbreviatedThunkName(MD, ContextualizedName))
ThunkName = getMangledThunk(MD, T, /* ElideOverrideInfo */ true);
else
ThunkName = ContextualizedName;
Manglings.emplace_back(ThunkName);
}
}
}
}

return Manglings;
Expand Down Expand Up @@ -569,11 +579,12 @@ class ASTNameGenerator::Implementation {
return BOS.str();
}

std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) {
std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T,
bool ElideOverrideInfo) {
std::string FrontendBuf;
llvm::raw_string_ostream FOS(FrontendBuf);

MC->mangleThunk(MD, T, FOS);
MC->mangleThunk(MD, T, ElideOverrideInfo, FOS);

std::string BackendBuf;
llvm::raw_string_ostream BOS(BackendBuf);
Expand Down
92 changes: 68 additions & 24 deletions clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,16 +159,18 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
const MethodVFTableLocation &ML,
raw_ostream &Out) override;
void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
raw_ostream &) override;
bool ElideOverrideInfo, raw_ostream &) override;
void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &ThisAdjustment,
const ThunkInfo &Thunk, bool ElideOverrideInfo,
raw_ostream &) override;
void mangleCXXVFTable(const CXXRecordDecl *Derived,
ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) override;
void mangleCXXVBTable(const CXXRecordDecl *Derived,
ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) override;

void mangleCXXVTable(const CXXRecordDecl *, raw_ostream &) override;
void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD,
const CXXRecordDecl *DstRD,
raw_ostream &Out) override;
Expand Down Expand Up @@ -447,8 +449,8 @@ class MicrosoftCXXNameMangler {
void mangleDecayedArrayType(const ArrayType *T);
void mangleArrayType(const ArrayType *T);
void mangleFunctionClass(const FunctionDecl *FD);
void mangleCallingConvention(CallingConv CC);
void mangleCallingConvention(const FunctionType *T);
void mangleCallingConvention(CallingConv CC, SourceRange Range);
void mangleCallingConvention(const FunctionType *T, SourceRange Range);
void mangleIntegerLiteral(const llvm::APSInt &Number,
const NonTypeTemplateParmDecl *PD = nullptr,
QualType TemplateArgType = QualType());
Expand Down Expand Up @@ -888,7 +890,8 @@ void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk(
Out << "$B";
mangleNumber(OffsetInVFTable);
Out << 'A';
mangleCallingConvention(MD->getType()->castAs<FunctionProtoType>());
mangleCallingConvention(MD->getType()->castAs<FunctionProtoType>(),
MD->getSourceRange());
}

void MicrosoftCXXNameMangler::mangleName(GlobalDecl GD) {
Expand Down Expand Up @@ -2768,7 +2771,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
mangleQualifiers(Quals, /*IsMember=*/false);
}

mangleCallingConvention(CC);
mangleCallingConvention(CC, Range);

// <return-type> ::= <type>
// ::= @ # structors (they have no declared return type)
Expand Down Expand Up @@ -2949,7 +2952,8 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
Out << 'Y';
}
}
void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC,
SourceRange Range) {
// <calling-convention> ::= A # __cdecl
// ::= B # __export __cdecl
// ::= C # __pascal
Expand All @@ -2962,7 +2966,10 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
// ::= J # __export __fastcall
// ::= Q # __vectorcall
// ::= S # __attribute__((__swiftcall__)) // Clang-only
// ::= T # __attribute__((__swiftasynccall__))
// ::= W # __attribute__((__swiftasynccall__))
// ::= U # __attribute__((__preserve_most__))
// ::= V # __attribute__((__preserve_none__)) //
// Clang-only
// // Clang-only
// ::= w # __regcall
// ::= x # __regcall4
Expand All @@ -2974,28 +2981,55 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {

switch (CC) {
default:
llvm_unreachable("Unsupported CC for mangling");
break;
case CC_Win64:
case CC_X86_64SysV:
case CC_C: Out << 'A'; break;
case CC_X86Pascal: Out << 'C'; break;
case CC_X86ThisCall: Out << 'E'; break;
case CC_X86StdCall: Out << 'G'; break;
case CC_X86FastCall: Out << 'I'; break;
case CC_X86VectorCall: Out << 'Q'; break;
case CC_Swift: Out << 'S'; break;
case CC_SwiftAsync: Out << 'W'; break;
case CC_PreserveMost: Out << 'U'; break;
case CC_C:
Out << 'A';
return;
case CC_X86Pascal:
Out << 'C';
return;
case CC_X86ThisCall:
Out << 'E';
return;
case CC_X86StdCall:
Out << 'G';
return;
case CC_X86FastCall:
Out << 'I';
return;
case CC_X86VectorCall:
Out << 'Q';
return;
case CC_Swift:
Out << 'S';
return;
case CC_SwiftAsync:
Out << 'W';
return;
case CC_PreserveMost:
Out << 'U';
return;
case CC_PreserveNone:
Out << 'V';
return;
case CC_X86RegCall:
if (getASTContext().getLangOpts().RegCall4)
Out << "x";
else
Out << "w";
break;
return;
}

DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, "cannot mangle this calling convention yet");
Diags.Report(Range.getBegin(), DiagID) << Range;
}
void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
mangleCallingConvention(T->getCallConv());
void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T,
SourceRange Range) {
mangleCallingConvention(T->getCallConv(), Range);
}

void MicrosoftCXXNameMangler::mangleThrowSpecification(
Expand Down Expand Up @@ -3715,6 +3749,7 @@ void MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk(

void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
bool /*ElideOverrideInfo*/,
raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Expand All @@ -3736,9 +3771,11 @@ void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
DeclForFPT->getType()->castAs<FunctionProtoType>(), MD);
}

void MicrosoftMangleContextImpl::mangleCXXDtorThunk(
const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &Adjustment, raw_ostream &Out) {
void MicrosoftMangleContextImpl::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
CXXDtorType Type,
const ThunkInfo &Thunk,
bool /*ElideOverrideInfo*/,
raw_ostream &Out) {
// FIXME: Actually, the dtor thunk should be emitted for vector deleting
// dtors rather than scalar deleting dtors. Just use the vector deleting dtor
// mangling manually until we support both deleting dtor types.
Expand All @@ -3747,6 +3784,7 @@ void MicrosoftMangleContextImpl::mangleCXXDtorThunk(
MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type);
Mangler.getStream() << "??_E";
Mangler.mangleName(DD->getParent());
auto &Adjustment = Thunk.This;
mangleThunkThisAdjustment(DD->getAccess(), Adjustment, Mangler, MHO);
Mangler.mangleFunctionType(DD->getType()->castAs<FunctionProtoType>(), DD);
}
Expand All @@ -3771,6 +3809,12 @@ void MicrosoftMangleContextImpl::mangleCXXVFTable(
Mangler.getStream() << '@';
}

void MicrosoftMangleContextImpl::mangleCXXVTable(const CXXRecordDecl *Derived,
raw_ostream &Out) {
// TODO: Determine appropriate mangling for MSABI
mangleCXXVFTable(Derived, {}, Out);
}

void MicrosoftMangleContextImpl::mangleCXXVBTable(
const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath,
raw_ostream &Out) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/StmtOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements the subclesses of Stmt class declared in StmtOpenMP.h
// This file implements the subclasses of Stmt class declared in StmtOpenMP.h
//
//===----------------------------------------------------------------------===//

Expand Down
105 changes: 99 additions & 6 deletions clang/lib/AST/VTableBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1147,11 +1147,41 @@ void ItaniumVTableBuilder::ComputeThisAdjustments() {
continue;

// Add it.
VTableThunks[VTableIndex].This = ThisAdjustment;
auto SetThisAdjustmentThunk = [&](uint64_t Idx) {
// If a this pointer adjustment is required, record the method that
// created the vtable entry. MD is not necessarily the method that
// created the entry since derived classes overwrite base class
// information in MethodInfoMap, hence findOriginalMethodInMap is called
// here.
//
// For example, in the following class hierarchy, if MD = D1::m and
// Overrider = D2:m, the original method that created the entry is B0:m,
// which is what findOriginalMethodInMap(MD) returns:
//
// struct B0 { int a; virtual void m(); };
// struct D0 : B0 { int a; void m() override; };
// struct D1 : B0 { int a; void m() override; };
// struct D2 : D0, D1 { int a; void m() override; };
//
// We need to record the method because we cannot
// call findOriginalMethod to find the method that created the entry if
// the method in the entry requires adjustment.
//
// Do not set ThunkInfo::Method if Idx is already in VTableThunks. This
// can happen when covariant return adjustment is required too.
if (!VTableThunks.count(Idx)) {
const CXXMethodDecl *Method = VTables.findOriginalMethodInMap(MD);
VTableThunks[Idx].Method = Method;
VTableThunks[Idx].ThisType = Method->getThisType().getTypePtr();
}
VTableThunks[Idx].This = ThisAdjustment;
};

SetThisAdjustmentThunk(VTableIndex);

if (isa<CXXDestructorDecl>(MD)) {
// Add an adjustment for the deleting destructor as well.
VTableThunks[VTableIndex + 1].This = ThisAdjustment;
SetThisAdjustmentThunk(VTableIndex + 1);
}
}

Expand Down Expand Up @@ -1509,6 +1539,8 @@ void ItaniumVTableBuilder::AddMethods(
FindNearestOverriddenMethod(MD, PrimaryBases)) {
if (ComputeReturnAdjustmentBaseOffset(Context, MD,
OverriddenMD).isEmpty()) {
VTables.setOriginalMethod(MD, OverriddenMD);

// Replace the method info of the overridden method with our own
// method.
assert(MethodInfoMap.count(OverriddenMD) &&
Expand Down Expand Up @@ -1547,7 +1579,8 @@ void ItaniumVTableBuilder::AddMethods(

// This is a virtual thunk for the most derived class, add it.
AddThunk(Overrider.Method,
ThunkInfo(ThisAdjustment, ReturnAdjustment));
ThunkInfo(ThisAdjustment, ReturnAdjustment,
OverriddenMD->getThisType().getTypePtr()));
}
}

Expand Down Expand Up @@ -1615,6 +1648,15 @@ void ItaniumVTableBuilder::AddMethods(
ReturnAdjustment ReturnAdjustment =
ComputeReturnAdjustment(ReturnAdjustmentOffset);

// If a return adjustment is required, record the method that created the
// vtable entry. We need to record the method because we cannot call
// findOriginalMethod to find the method that created the entry if the
// method in the entry requires adjustment.
if (!ReturnAdjustment.isEmpty()) {
VTableThunks[Components.size()].Method = MD;
VTableThunks[Components.size()].ThisType = MD->getThisType().getTypePtr();
}

AddMethod(Overrider.Method, ReturnAdjustment);
}
}
Expand Down Expand Up @@ -1890,11 +1932,31 @@ void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
}
}

static void printThunkMethod(const ThunkInfo &Info, raw_ostream &Out) {
if (!Info.Method)
return;
std::string Str = PredefinedExpr::ComputeName(
PredefinedIdentKind::PrettyFunctionNoVirtual, Info.Method);
Out << " method: " << Str;
}

/// dumpLayout - Dump the vtable layout.
void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
// FIXME: write more tests that actually use the dumpLayout output to prevent
// ItaniumVTableBuilder regressions.

Out << "Original map\n";

for (const auto &P : VTables.getOriginalMethodMap()) {
std::string Str0 =
PredefinedExpr::ComputeName(PredefinedIdentKind::PrettyFunctionNoVirtual,
P.first);
std::string Str1 =
PredefinedExpr::ComputeName(PredefinedIdentKind::PrettyFunctionNoVirtual,
P.second);
Out << " " << Str0 << " -> " << Str1 << "\n";
}

if (isBuildingConstructorVTable()) {
Out << "Construction vtable for ('";
MostDerivedClass->printQualifiedName(Out);
Expand Down Expand Up @@ -1978,6 +2040,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
}

Out << ']';
printThunkMethod(Thunk, Out);
}

// If this function pointer has a 'this' pointer adjustment, dump it.
Expand All @@ -1991,6 +2054,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
}

Out << ']';
printThunkMethod(Thunk, Out);
}
}

Expand Down Expand Up @@ -2027,6 +2091,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {

Out << ']';
}
printThunkMethod(Thunk, Out);
}

break;
Expand Down Expand Up @@ -2125,7 +2190,6 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {

ThunkInfoVectorTy ThunksVector = Thunks[MD];
llvm::sort(ThunksVector, [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
assert(LHS.Method == nullptr && RHS.Method == nullptr);
return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
});

Expand Down Expand Up @@ -2314,6 +2378,35 @@ ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
return I->second;
}

GlobalDecl ItaniumVTableContext::findOriginalMethod(GlobalDecl GD) {
const auto *MD = cast<CXXMethodDecl>(GD.getDecl());
computeVTableRelatedInformation(MD->getParent());
const CXXMethodDecl *OriginalMD = findOriginalMethodInMap(MD);

if (const auto *DD = dyn_cast<CXXDestructorDecl>(OriginalMD))
return GlobalDecl(DD, GD.getDtorType());
return OriginalMD;
}

const CXXMethodDecl *
ItaniumVTableContext::findOriginalMethodInMap(const CXXMethodDecl *MD) const {
// Traverse the chain of virtual methods until we find the method that added
// the v-table slot.
while (true) {
auto I = OriginalMethodMap.find(MD);

// MD doesn't exist in OriginalMethodMap, so it must be the method we are
// looking for.
if (I == OriginalMethodMap.end())
break;

// Set MD to the overridden method.
MD = I->second;
}

return MD;
}

static std::unique_ptr<VTableLayout>
CreateVTableLayout(const ItaniumVTableBuilder &Builder) {
SmallVector<VTableLayout::VTableThunkTy, 1>
Expand Down Expand Up @@ -3094,9 +3187,9 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
ReturnAdjustmentOffset.VirtualBase);
}
}

auto ThisType = (OverriddenMD ? OverriddenMD : MD)->getThisType().getTypePtr();
AddMethod(FinalOverriderMD,
ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment, ThisType,
ForceReturnAdjustmentMangling ? MD : nullptr));
}
}
Expand Down
17 changes: 11 additions & 6 deletions clang/lib/Analysis/FlowSensitive/Transfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,17 +391,22 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
}
case UO_PreInc:
case UO_PreDec:
// Propagate the storage location, but don't create a new value; to
// avoid generating unnecessary values, we leave it to the specific
// analysis to do this if desired.
// Propagate the storage location and clear out any value associated with
// it (to represent the fact that the value has definitely changed).
// To avoid generating unnecessary values, we leave it to the specific
// analysis to create a new value if desired.
propagateStorageLocation(*S->getSubExpr(), *S, Env);
if (StorageLocation *Loc = Env.getStorageLocation(*S->getSubExpr()))
Env.clearValue(*Loc);
break;
case UO_PostInc:
case UO_PostDec:
// Propagate the old value, but don't create a new value; to avoid
// generating unnecessary values, we leave it to the specific analysis
// to do this if desired.
// Propagate the old value, then clear out any value associated with the
// storage location (to represent the fact that the value has definitely
// changed). See above for rationale.
propagateValue(*S->getSubExpr(), *S, Env);
if (StorageLocation *Loc = Env.getStorageLocation(*S->getSubExpr()))
Env.clearValue(*Loc);
break;
default:
break;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ static const CudaArchToStringMap arch_names[] = {
{CudaArch::GFX12_GENERIC, "gfx12-generic", "compute_amdgcn"},
GFX(1200), // gfx1200
GFX(1201), // gfx1201
{CudaArch::AMDGCNSPIRV, "amdgcnspirv", "compute_amdgcn"},
{CudaArch::Generic, "generic", ""},
// clang-format on
};
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1536,6 +1536,7 @@ WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
case CC_OpenCLKernel:
case CC_PreserveMost:
case CC_PreserveAll:
case CC_PreserveNone:
case CC_Swift:
case CC_SwiftAsync:
case CC_Win64:
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/NVPTX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
case CudaArch::GFX12_GENERIC:
case CudaArch::GFX1200:
case CudaArch::GFX1201:
case CudaArch::AMDGCNSPIRV:
case CudaArch::Generic:
case CudaArch::LAST:
break;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/BackendConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class BackendConsumer : public ASTConsumer {
void HandleVTable(CXXRecordDecl *RD) override;

// Links each entry in LinkModules into our module. Returns true on error.
bool LinkInModules(llvm::Module *M, bool ShouldLinkFiles = true);
bool LinkInModules(llvm::Module *M);

/// Get the best possible source location to represent a diagnostic that
/// may have associated debug info.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline(

// Link against bitcodes supplied via the -mlink-builtin-bitcode option
if (CodeGenOpts.LinkBitcodePostopt)
MPM.addPass(LinkInModulesPass(BC, false));
MPM.addPass(LinkInModulesPass(BC));

// Add a verifier pass if requested. We don't have to do this if the action
// requires code generation because there will already be a verifier pass in
Expand Down
76 changes: 50 additions & 26 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3505,6 +3505,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_trap:
EmitTrapCall(Intrinsic::trap);
return RValue::get(nullptr);
case Builtin::BI__builtin_verbose_trap: {
llvm::DILocation *TrapLocation = Builder.getCurrentDebugLocation();
if (getDebugInfo()) {
TrapLocation = getDebugInfo()->CreateTrapFailureMessageFor(
TrapLocation, *E->getArg(0)->tryEvaluateString(getContext()),
*E->getArg(1)->tryEvaluateString(getContext()));
}
ApplyDebugLocation ApplyTrapDI(*this, TrapLocation);
// Currently no attempt is made to prevent traps from being merged.
EmitTrapCall(Intrinsic::trap);
return RValue::get(nullptr);
}
case Builtin::BI__debugbreak:
EmitTrapCall(Intrinsic::debugtrap);
return RValue::get(nullptr);
Expand Down Expand Up @@ -18467,6 +18479,22 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
CGM.getIntrinsic(Intrinsic::amdgcn_update_dpp, Args[0]->getType());
return Builder.CreateCall(F, Args);
}
case AMDGPU::BI__builtin_amdgcn_permlane16:
case AMDGPU::BI__builtin_amdgcn_permlanex16:
return emitBuiltinWithOneOverloadedType<6>(
*this, E,
BuiltinID == AMDGPU::BI__builtin_amdgcn_permlane16
? Intrinsic::amdgcn_permlane16
: Intrinsic::amdgcn_permlanex16);
case AMDGPU::BI__builtin_amdgcn_permlane64:
return emitBuiltinWithOneOverloadedType<1>(*this, E,
Intrinsic::amdgcn_permlane64);
case AMDGPU::BI__builtin_amdgcn_readlane:
return emitBuiltinWithOneOverloadedType<2>(*this, E,
Intrinsic::amdgcn_readlane);
case AMDGPU::BI__builtin_amdgcn_readfirstlane:
return emitBuiltinWithOneOverloadedType<1>(*this, E,
Intrinsic::amdgcn_readfirstlane);
case AMDGPU::BI__builtin_amdgcn_div_fixup:
case AMDGPU::BI__builtin_amdgcn_div_fixupf:
case AMDGPU::BI__builtin_amdgcn_div_fixuph:
Expand Down Expand Up @@ -18604,28 +18632,6 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
Function *F = CGM.getIntrinsic(Intrin, { Src0->getType() });
return Builder.CreateCall(F, { Src0, Builder.getFalse() });
}
case AMDGPU::BI__builtin_amdgcn_ds_fminf:
case AMDGPU::BI__builtin_amdgcn_ds_fmaxf: {
Intrinsic::ID Intrin;
switch (BuiltinID) {
case AMDGPU::BI__builtin_amdgcn_ds_fminf:
Intrin = Intrinsic::amdgcn_ds_fmin;
break;
case AMDGPU::BI__builtin_amdgcn_ds_fmaxf:
Intrin = Intrinsic::amdgcn_ds_fmax;
break;
}
llvm::Value *Src0 = EmitScalarExpr(E->getArg(0));
llvm::Value *Src1 = EmitScalarExpr(E->getArg(1));
llvm::Value *Src2 = EmitScalarExpr(E->getArg(2));
llvm::Value *Src3 = EmitScalarExpr(E->getArg(3));
llvm::Value *Src4 = EmitScalarExpr(E->getArg(4));
llvm::Function *F = CGM.getIntrinsic(Intrin, { Src1->getType() });
llvm::FunctionType *FTy = F->getFunctionType();
llvm::Type *PTy = FTy->getParamType(0);
Src0 = Builder.CreatePointerBitCastOrAddrSpaceCast(Src0, PTy);
return Builder.CreateCall(F, { Src0, Src1, Src2, Src3, Src4 });
}
case AMDGPU::BI__builtin_amdgcn_global_atomic_fadd_f64:
case AMDGPU::BI__builtin_amdgcn_global_atomic_fadd_f32:
case AMDGPU::BI__builtin_amdgcn_global_atomic_fadd_v2f16:
Expand Down Expand Up @@ -19059,11 +19065,13 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
case AMDGPU::BI__builtin_amdgcn_atomic_inc64:
case AMDGPU::BI__builtin_amdgcn_atomic_dec32:
case AMDGPU::BI__builtin_amdgcn_atomic_dec64:
case AMDGPU::BI__builtin_amdgcn_ds_faddf:
case AMDGPU::BI__builtin_amdgcn_ds_atomic_fadd_f64:
case AMDGPU::BI__builtin_amdgcn_ds_atomic_fadd_f32:
case AMDGPU::BI__builtin_amdgcn_ds_atomic_fadd_v2f16:
case AMDGPU::BI__builtin_amdgcn_ds_atomic_fadd_v2bf16: {
case AMDGPU::BI__builtin_amdgcn_ds_atomic_fadd_v2bf16:
case AMDGPU::BI__builtin_amdgcn_ds_faddf:
case AMDGPU::BI__builtin_amdgcn_ds_fminf:
case AMDGPU::BI__builtin_amdgcn_ds_fmaxf: {
llvm::AtomicRMWInst::BinOp BinOp;
switch (BuiltinID) {
case AMDGPU::BI__builtin_amdgcn_atomic_inc32:
Expand All @@ -19081,6 +19089,12 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
case AMDGPU::BI__builtin_amdgcn_ds_atomic_fadd_v2bf16:
BinOp = llvm::AtomicRMWInst::FAdd;
break;
case AMDGPU::BI__builtin_amdgcn_ds_fminf:
BinOp = llvm::AtomicRMWInst::FMin;
break;
case AMDGPU::BI__builtin_amdgcn_ds_fmaxf:
BinOp = llvm::AtomicRMWInst::FMax;
break;
}

Address Ptr = CheckAtomicAlignment(*this, E);
Expand All @@ -19090,8 +19104,10 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,

bool Volatile;

if (BuiltinID == AMDGPU::BI__builtin_amdgcn_ds_faddf) {
// __builtin_amdgcn_ds_faddf has an explicit volatile argument
if (BuiltinID == AMDGPU::BI__builtin_amdgcn_ds_faddf ||
BuiltinID == AMDGPU::BI__builtin_amdgcn_ds_fminf ||
BuiltinID == AMDGPU::BI__builtin_amdgcn_ds_fmaxf) {
// __builtin_amdgcn_ds_faddf/fminf/fmaxf has an explicit volatile argument
Volatile =
cast<ConstantInt>(EmitScalarExpr(E->getArg(4)))->getZExtValue();
} else {
Expand Down Expand Up @@ -19135,6 +19151,14 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
case AMDGPU::BI__builtin_amdgcn_make_buffer_rsrc:
return emitBuiltinWithOneOverloadedType<4>(
*this, E, Intrinsic::amdgcn_make_buffer_rsrc);
case AMDGPU::BI__builtin_amdgcn_raw_buffer_store_b8:
case AMDGPU::BI__builtin_amdgcn_raw_buffer_store_b16:
case AMDGPU::BI__builtin_amdgcn_raw_buffer_store_b32:
case AMDGPU::BI__builtin_amdgcn_raw_buffer_store_b64:
case AMDGPU::BI__builtin_amdgcn_raw_buffer_store_b96:
case AMDGPU::BI__builtin_amdgcn_raw_buffer_store_b128:
return emitBuiltinWithOneOverloadedType<5>(
*this, E, Intrinsic::amdgcn_raw_ptr_buffer_store);
default:
return nullptr;
}
Expand Down
11 changes: 10 additions & 1 deletion clang/lib/CodeGen/CGCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,16 @@ static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF,
CGF.Builder.CreateConstInBoundsGEP1_64(Ty, VTable, VTableIndex, "vfnkxt");
llvm::Value *VFunc = CGF.Builder.CreateAlignedLoad(
Ty, VFuncPtr, llvm::Align(CGF.PointerAlignInBytes));
CGCallee Callee(GD, VFunc);

CGPointerAuthInfo PointerAuth;
if (auto &Schema =
CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers) {
GlobalDecl OrigMD =
CGM.getItaniumVTableContext().findOriginalMethod(GD.getCanonicalDecl());
PointerAuth = CGF.EmitPointerAuthInfo(Schema, VFuncPtr, OrigMD, QualType());
}

CGCallee Callee(GD, VFunc, PointerAuth);
return Callee;
}

Expand Down
14 changes: 8 additions & 6 deletions clang/lib/CodeGen/CGCXXABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,13 +504,15 @@ class CGCXXABI {
virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable,
GlobalDecl GD, bool ReturnAdjustment) = 0;

virtual llvm::Value *performThisAdjustment(CodeGenFunction &CGF,
Address This,
const ThisAdjustment &TA) = 0;
virtual llvm::Value *
performThisAdjustment(CodeGenFunction &CGF, Address This,
const CXXRecordDecl *UnadjustedClass,
const ThunkInfo &TI) = 0;

virtual llvm::Value *performReturnAdjustment(CodeGenFunction &CGF,
Address Ret,
const ReturnAdjustment &RA) = 0;
virtual llvm::Value *
performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
const CXXRecordDecl *UnadjustedClass,
const ReturnAdjustment &RA) = 0;

virtual void EmitReturnFromThunk(CodeGenFunction &CGF,
RValue RV, QualType ResultType);
Expand Down
30 changes: 29 additions & 1 deletion clang/lib/CodeGen/CGClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2588,6 +2588,11 @@ void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) {
// the same addr space. Note that this might not be LLVM address space 0.
VTableField = VTableField.withElementType(PtrTy);

if (auto AuthenticationInfo = CGM.getVTablePointerAuthInfo(
this, Vptr.Base.getBase(), VTableField.emitRawPointer(*this)))
VTableAddressPoint =
EmitPointerAuthSign(*AuthenticationInfo, VTableAddressPoint);

llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField);
TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(PtrTy);
CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
Expand Down Expand Up @@ -2681,12 +2686,35 @@ void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) {

llvm::Value *CodeGenFunction::GetVTablePtr(Address This,
llvm::Type *VTableTy,
const CXXRecordDecl *RD) {
const CXXRecordDecl *RD,
VTableAuthMode AuthMode) {
Address VTablePtrSrc = This.withElementType(VTableTy);
llvm::Instruction *VTable = Builder.CreateLoad(VTablePtrSrc, "vtable");
TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(VTableTy);
CGM.DecorateInstructionWithTBAA(VTable, TBAAInfo);

if (auto AuthenticationInfo =
CGM.getVTablePointerAuthInfo(this, RD, This.emitRawPointer(*this))) {
if (AuthMode != VTableAuthMode::UnsafeUbsanStrip) {
VTable = cast<llvm::Instruction>(
EmitPointerAuthAuth(*AuthenticationInfo, VTable));
if (AuthMode == VTableAuthMode::MustTrap) {
// This is clearly suboptimal but until we have an ability
// to rely on the authentication intrinsic trapping and force
// an authentication to occur we don't really have a choice.
VTable =
cast<llvm::Instruction>(Builder.CreateBitCast(VTable, Int8PtrTy));
Builder.CreateLoad(RawAddress(VTable, Int8Ty, CGM.getPointerAlign()),
/* IsVolatile */ true);
}
} else {
VTable = cast<llvm::Instruction>(EmitPointerAuthAuth(
CGPointerAuthInfo(0, PointerAuthenticationMode::Strip, false, false,
nullptr),
VTable));
}
}

if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
CGM.getCodeGenOpts().StrictVTablePointers)
CGM.DecorateInstructionWithInvariantGroup(VTable, RD);
Expand Down
40 changes: 40 additions & 0 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/ModuleMap.h"
Expand Down Expand Up @@ -1731,6 +1732,28 @@ llvm::DIType *CGDebugInfo::createFieldType(
offsetInBits, flags, debugType, Annotations);
}

llvm::DISubprogram *
CGDebugInfo::createInlinedTrapSubprogram(StringRef FuncName,
llvm::DIFile *FileScope) {
// We are caching the subprogram because we don't want to duplicate
// subprograms with the same message. Note that `SPFlagDefinition` prevents
// subprograms from being uniqued.
llvm::DISubprogram *&SP = InlinedTrapFuncMap[FuncName];

if (!SP) {
llvm::DISubroutineType *DIFnTy = DBuilder.createSubroutineType(nullptr);
SP = DBuilder.createFunction(
/*Scope=*/FileScope, /*Name=*/FuncName, /*LinkageName=*/StringRef(),
/*File=*/FileScope, /*LineNo=*/0, /*Ty=*/DIFnTy,
/*ScopeLine=*/0,
/*Flags=*/llvm::DINode::FlagArtificial,
/*SPFlags=*/llvm::DISubprogram::SPFlagDefinition,
/*TParams=*/nullptr, /*ThrownTypes=*/nullptr, /*Annotations=*/nullptr);
}

return SP;
}

void CGDebugInfo::CollectRecordLambdaFields(
const CXXRecordDecl *CXXDecl, SmallVectorImpl<llvm::Metadata *> &elements,
llvm::DIType *RecordTy) {
Expand Down Expand Up @@ -3527,6 +3550,23 @@ llvm::DIMacroFile *CGDebugInfo::CreateTempMacroFile(llvm::DIMacroFile *Parent,
return DBuilder.createTempMacroFile(Parent, Line, FName);
}

llvm::DILocation *CGDebugInfo::CreateTrapFailureMessageFor(
llvm::DebugLoc TrapLocation, StringRef Category, StringRef FailureMsg) {
// Create a debug location from `TrapLocation` that adds an artificial inline
// frame.
SmallString<64> FuncName(ClangTrapPrefix);

FuncName += "$";
FuncName += Category;
FuncName += "$";
FuncName += FailureMsg;

llvm::DISubprogram *TrapSP =
createInlinedTrapSubprogram(FuncName, TrapLocation->getFile());
return llvm::DILocation::get(CGM.getLLVMContext(), /*Line=*/0, /*Column=*/0,
/*Scope=*/TrapSP, /*InlinedAt=*/TrapLocation);
}

static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
Qualifiers Quals;
do {
Expand Down
22 changes: 22 additions & 0 deletions clang/lib/CodeGen/CGDebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Allocator.h"
#include <map>
#include <optional>
#include <string>

namespace llvm {
class MDNode;
Expand Down Expand Up @@ -346,6 +348,14 @@ class CGDebugInfo {
const FieldDecl *BitFieldDecl, const llvm::DIDerivedType *BitFieldDI,
llvm::ArrayRef<llvm::Metadata *> PreviousFieldsDI, const RecordDecl *RD);

/// A cache that maps names of artificial inlined functions to subprograms.
llvm::StringMap<llvm::DISubprogram *> InlinedTrapFuncMap;

/// A function that returns the subprogram corresponding to the artificial
/// inlined function for traps.
llvm::DISubprogram *createInlinedTrapSubprogram(StringRef FuncName,
llvm::DIFile *FileScope);

/// Helpers for collecting fields of a record.
/// @{
void CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl,
Expand Down Expand Up @@ -608,6 +618,18 @@ class CGDebugInfo {
return CoroutineParameterMappings;
}

/// Create a debug location from `TrapLocation` that adds an artificial inline
/// frame where the frame name is
///
/// * `<Prefix>:<Category>:<FailureMsg>`
///
/// `<Prefix>` is "__clang_trap_msg".
///
/// This is used to store failure reasons for traps.
llvm::DILocation *CreateTrapFailureMessageFor(llvm::DebugLoc TrapLocation,
StringRef Category,
StringRef FailureMsg);

private:
/// Emit call to llvm.dbg.declare for a variable declaration.
/// Returns a pointer to the DILocalVariable associated with the
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -830,8 +830,14 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// Load the vptr, and mix it with TypeHash.
llvm::Value *TypeHash =
llvm::ConstantInt::get(Int64Ty, xxh3_64bits(Out.str()));

llvm::Type *VPtrTy = llvm::PointerType::get(IntPtrTy, 0);
Address VPtrAddr(Ptr, IntPtrTy, getPointerAlign());
llvm::Value *VPtrVal = Builder.CreateLoad(VPtrAddr);
llvm::Value *VPtrVal = GetVTablePtr(VPtrAddr, VPtrTy,
Ty->getAsCXXRecordDecl(),
VTableAuthMode::UnsafeUbsanStrip);
VPtrVal = Builder.CreateBitOrPointerCast(VPtrVal, IntPtrTy);

llvm::Value *Hash =
emitHashMix(Builder, TypeHash, Builder.CreateZExt(VPtrVal, Int64Ty));
Hash = Builder.CreateTrunc(Hash, IntPtrTy);
Expand Down
46 changes: 45 additions & 1 deletion clang/lib/CodeGen/CGExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,13 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
llvm::Constant *VTableAddressPoint =
CGM.getCXXABI().getVTableAddressPoint(BaseSubobject(CD, Offset),
VTableClass);
if (auto Authentication =
CGM.getVTablePointerAuthentication(VTableClass)) {
VTableAddressPoint = Emitter.tryEmitConstantSignedPointer(
VTableAddressPoint, *Authentication);
if (!VTableAddressPoint)
return false;
}
if (!AppendBytes(Offset, VTableAddressPoint))
return false;
}
Expand Down Expand Up @@ -1647,7 +1654,7 @@ namespace {
// messing around with llvm::Constant structures, which never itself
// does anything that should be visible in compiler output.
for (auto &entry : Locations) {
assert(entry.first->getParent() == nullptr && "not a placeholder!");
assert(entry.first->getName() == "" && "not a placeholder!");
entry.first->replaceAllUsesWith(entry.second);
entry.first->eraseFromParent();
}
Expand Down Expand Up @@ -1811,6 +1818,43 @@ llvm::Constant *ConstantEmitter::tryEmitPrivateForMemory(const APValue &value,
return (C ? emitForMemory(C, destType) : nullptr);
}

/// Try to emit a constant signed pointer, given a raw pointer and the
/// destination ptrauth qualifier.
///
/// This can fail if the qualifier needs address discrimination and the
/// emitter is in an abstract mode.
llvm::Constant *
ConstantEmitter::tryEmitConstantSignedPointer(llvm::Constant *UnsignedPointer,
PointerAuthQualifier Schema) {
assert(Schema && "applying trivial ptrauth schema");

if (Schema.hasKeyNone())
return UnsignedPointer;

unsigned Key = Schema.getKey();

// Create an address placeholder if we're using address discrimination.
llvm::GlobalValue *StorageAddress = nullptr;
if (Schema.isAddressDiscriminated()) {
// We can't do this if the emitter is in an abstract state.
if (isAbstract())
return nullptr;

StorageAddress = getCurrentAddrPrivate();
}

llvm::ConstantInt *Discriminator =
llvm::ConstantInt::get(CGM.IntPtrTy, Schema.getExtraDiscriminator());

llvm::Constant *SignedPointer = CGM.getConstantSignedPointer(
UnsignedPointer, Key, StorageAddress, Discriminator);

if (Schema.isAddressDiscriminated())
registerCurrentAddrPrivate(SignedPointer, StorageAddress);

return SignedPointer;
}

llvm::Constant *ConstantEmitter::emitForMemory(CodeGenModule &CGM,
llvm::Constant *C,
QualType destType) {
Expand Down
Loading