diff options
Diffstat (limited to 'clang/include')
23 files changed, 373 insertions, 48 deletions
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index a3c67a6..a4a1bb9 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -3395,9 +3395,10 @@ inline UnsignedOrNone getExpandedPackSize(const NamedDecl *Param) { return std::nullopt; } -/// Internal helper used by Subst* nodes to retrieve the parameter list -/// for their AssociatedDecl. -TemplateParameterList *getReplacedTemplateParameterList(const Decl *D); +/// Internal helper used by Subst* nodes to retrieve a parameter from the +/// AssociatedDecl, and the template argument substituted into it, if any. +std::tuple<NamedDecl *, TemplateArgument> +getReplacedTemplateParameter(Decl *D, unsigned Index); /// If we have a 'templated' declaration for a template, adjust 'D' to /// refer to the actual template. diff --git a/clang/include/clang/AST/HLSLResource.h b/clang/include/clang/AST/HLSLResource.h index 9cdd81b..7440050 100644 --- a/clang/include/clang/AST/HLSLResource.h +++ b/clang/include/clang/AST/HLSLResource.h @@ -69,6 +69,11 @@ struct ResourceBindingAttrs { assert(hasImplicitOrderID()); return RegBinding->getImplicitBindingOrderID(); } + + void setImplicitOrderID(unsigned Value) const { + assert(hasBinding() && !isExplicit() && !hasImplicitOrderID()); + RegBinding->setImplicitBindingOrderID(Value); + } }; } // namespace hlsl diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h index 6786b2f..625cc77 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -7082,10 +7082,6 @@ public: class SubstTemplateTypeParmPackType : public SubstPackType { friend class ASTContext; - /// A pointer to the set of template arguments that this - /// parameter pack is instantiated with. - const TemplateArgument *Arguments; - llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal; SubstTemplateTypeParmPackType(QualType Canon, Decl *AssociatedDecl, diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety.h index 512cb76..e54fc26 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety.h @@ -29,12 +29,18 @@ namespace clang::lifetimes { /// Enum to track the confidence level of a potential error. -enum class Confidence { +enum class Confidence : uint8_t { None, Maybe, // Reported as a potential error (-Wlifetime-safety-strict) Definite // Reported as a definite error (-Wlifetime-safety-permissive) }; +enum class LivenessKind : uint8_t { + Dead, // Not alive + Maybe, // Live on some path but not all paths (may-be-live) + Must // Live on all paths (must-be-live) +}; + class LifetimeSafetyReporter { public: LifetimeSafetyReporter() = default; @@ -55,6 +61,7 @@ class Fact; class FactManager; class LoanPropagationAnalysis; class ExpiredLoansAnalysis; +class LiveOriginAnalysis; struct LifetimeFactory; /// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type. @@ -89,6 +96,7 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, OriginID ID) { // TODO(opt): Consider using a bitset to represent the set of loans. using LoanSet = llvm::ImmutableSet<LoanID>; using OriginSet = llvm::ImmutableSet<OriginID>; +using OriginLoanMap = llvm::ImmutableMap<OriginID, LoanSet>; /// A `ProgramPoint` identifies a location in the CFG by pointing to a specific /// `Fact`. identified by a lifetime-related event (`Fact`). @@ -110,8 +118,16 @@ public: /// Returns the set of loans an origin holds at a specific program point. LoanSet getLoansAtPoint(OriginID OID, ProgramPoint PP) const; - /// Returns the set of loans that have expired at a specific program point. - std::vector<LoanID> getExpiredLoansAtPoint(ProgramPoint PP) const; + /// Returns the set of origins that are live at a specific program point, + /// along with the confidence level of their liveness. + /// + /// An origin is considered live if there are potential future uses of that + /// origin after the given program point. The confidence level indicates + /// whether the origin is definitely live (Definite) due to being domintated + /// by a set of uses or only possibly live (Maybe) only on some but not all + /// control flow paths. + std::vector<std::pair<OriginID, LivenessKind>> + getLiveOriginsAtPoint(ProgramPoint PP) const; /// Finds the OriginID for a given declaration. /// Returns a null optional if not found. @@ -138,7 +154,7 @@ private: std::unique_ptr<LifetimeFactory> Factory; std::unique_ptr<FactManager> FactMgr; std::unique_ptr<LoanPropagationAnalysis> LoanPropagation; - std::unique_ptr<ExpiredLoansAnalysis> ExpiredLoans; + std::unique_ptr<LiveOriginAnalysis> LiveOrigins; }; } // namespace internal } // namespace clang::lifetimes diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h index 9b53f1d..ea41eb3 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_H #define LLVM_CLANG_ANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_H +#include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/AST/Stmt.h" @@ -139,6 +140,12 @@ public: FixItList &&Fixes, const Decl *D, const FixitStrategy &VarTargetTypes) = 0; + // Invoked when an array subscript operator[] is used on a + // std::unique_ptr<T[]>. + virtual void handleUnsafeUniquePtrArrayAccess(const DynTypedNode &Node, + bool IsRelatedToDecl, + ASTContext &Ctx) = 0; + #ifndef NDEBUG public: bool areDebugNotesRequested() { diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index 09fa510..fae5f8b 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -38,6 +38,7 @@ WARNING_GADGET(PointerArithmetic) WARNING_GADGET(UnsafeBufferUsageAttr) WARNING_GADGET(UnsafeBufferUsageCtorAttr) WARNING_GADGET(DataInvocation) +WARNING_GADGET(UniquePtrArrayAccess) WARNING_OPTIONAL_GADGET(UnsafeLibcFunctionCall) WARNING_OPTIONAL_GADGET(SpanTwoParamConstructor) // Uses of `std::span(arg0, arg1)` FIXABLE_GADGET(ULCArraySubscript) // `DRE[any]` in an Unspecified Lvalue Context diff --git a/clang/include/clang/Basic/BuiltinsX86.td b/clang/include/clang/Basic/BuiltinsX86.td index 4165225..217589d 100644 --- a/clang/include/clang/Basic/BuiltinsX86.td +++ b/clang/include/clang/Basic/BuiltinsX86.td @@ -123,13 +123,16 @@ let Attributes = [Const, NoThrow, RequiredVectorWidth<128>] in { def Op#d128 : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">; } - def pmaddubsw128 : X86Builtin<"_Vector<8, short>(_Vector<16, char>, _Vector<16, char>)">; def pmulhrsw128 : X86Builtin<"_Vector<8, short>(_Vector<8, short>, _Vector<8, short>)">; def pshufb128 : X86Builtin<"_Vector<16, char>(_Vector<16, char>, _Vector<16, char>)">; def psignb128 : X86Builtin<"_Vector<16, char>(_Vector<16, char>, _Vector<16, char>)">; def psignw128 : X86Builtin<"_Vector<8, short>(_Vector<8, short>, _Vector<8, short>)">; def psignd128 : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">; } + + let Features = "ssse3", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in { + def pmaddubsw128 : X86Builtin<"_Vector<8, short>(_Vector<16, char>, _Vector<16, char>)">; + } } // AVX @@ -278,13 +281,14 @@ let Features = "sse2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] i def psllw128 : X86Builtin<"_Vector<8, short>(_Vector<8, short>, _Vector<8, short>)">; def pslld128 : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">; def psllq128 : X86Builtin<"_Vector<2, long long int>(_Vector<2, long long int>, _Vector<2, long long int>)">; - def pmaddwd128 : X86Builtin<"_Vector<4, int>(_Vector<8, short>, _Vector<8, short>)">; def pslldqi128_byteshift : X86Builtin<"_Vector<16, char>(_Vector<16, char>, _Constant int)">; def psrldqi128_byteshift : X86Builtin<"_Vector<16, char>(_Vector<16, char>, _Constant int)">; } let Features = "sse2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in { + def pmaddwd128 : X86Builtin<"_Vector<4, int>(_Vector<8, short>, _Vector<8, short>)">; + def pmuludq128 : X86Builtin<"_Vector<2, long long int>(_Vector<4, int>, _Vector<4, int>)">; def psllwi128 : X86Builtin<"_Vector<8, short>(_Vector<8, short>, int)">; @@ -581,8 +585,6 @@ let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] i def phsubw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">; def phsubd256 : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">; def phsubsw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">; - def pmaddubsw256 : X86Builtin<"_Vector<16, short>(_Vector<32, char>, _Vector<32, char>)">; - def pmaddwd256 : X86Builtin<"_Vector<8, int>(_Vector<16, short>, _Vector<16, short>)">; def pmovmskb256 : X86Builtin<"int(_Vector<32, char>)">; def pmulhrsw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">; def psadbw256 : X86Builtin<"_Vector<4, long long int>(_Vector<32, char>, _Vector<32, char>)">; @@ -619,6 +621,9 @@ let Features = "avx2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWi def pblendvb256 : X86Builtin<"_Vector<32, char>(_Vector<32, char>, _Vector<32, char>, _Vector<32, char>)">; + def pmaddubsw256 : X86Builtin<"_Vector<16, short>(_Vector<32, char>, _Vector<32, char>)">; + def pmaddwd256 : X86Builtin<"_Vector<8, int>(_Vector<16, short>, _Vector<16, short>)">; + def pmuldq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">; def pmuludq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">; @@ -1378,10 +1383,6 @@ let Features = "avx512f", Attributes = [NoThrow, Const, RequiredVectorWidth<512> def subps512 : X86Builtin<"_Vector<16, float>(_Vector<16, float>, _Vector<16, float>, _Constant int)">; } -let Features = "avx512bw", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in { - def pmaddubsw512 : X86Builtin<"_Vector<32, short>(_Vector<64, char>, _Vector<64, char>)">; - def pmaddwd512 : X86Builtin<"_Vector<16, int>(_Vector<32, short>, _Vector<32, short>)">; -} let Features = "avx512f", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in { def addss_round_mask : X86Builtin<"_Vector<4, float>(_Vector<4, float>, _Vector<4, float>, _Vector<4, float>, unsigned char, _Constant int)">; @@ -1999,6 +2000,8 @@ let Features = "avx512bw", Attributes = [NoThrow, Const, RequiredVectorWidth<512 } let Features = "avx512bw", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in { + def pmaddubsw512 : X86Builtin<"_Vector<32, short>(_Vector<64, char>, _Vector<64, char>)">; + def pmaddwd512 : X86Builtin<"_Vector<16, int>(_Vector<32, short>, _Vector<32, short>)">; def psllv32hi : X86Builtin<"_Vector<32, short>(_Vector<32, short>, _Vector<32, short>)">; def pshufhw512 : X86Builtin<"_Vector<32, short>(_Vector<32, short>, _Constant int)">; def pshuflw512 : X86Builtin<"_Vector<32, short>(_Vector<32, short>, _Constant int)">; diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt index 8173600..cfd165e 100644 --- a/clang/include/clang/Basic/CMakeLists.txt +++ b/clang/include/clang/Basic/CMakeLists.txt @@ -159,6 +159,9 @@ clang_tablegen(arm_mve_builtin_aliases.inc -gen-arm-mve-builtin-aliases clang_tablegen(arm_sve_builtins.inc -gen-arm-sve-builtins SOURCE arm_sve.td TARGET ClangARMSveBuiltins) +clang_tablegen(arm_sve_builtins.json -gen-arm-sve-builtins-json + SOURCE arm_sve.td + TARGET ClangARMSveBuiltinsJSON) clang_tablegen(arm_sve_builtin_cg.inc -gen-arm-sve-builtin-codegen SOURCE arm_sve.td TARGET ClangARMSveBuiltinCG) @@ -174,6 +177,9 @@ clang_tablegen(arm_sve_streaming_attrs.inc -gen-arm-sve-streaming-attrs clang_tablegen(arm_sme_builtins.inc -gen-arm-sme-builtins SOURCE arm_sme.td TARGET ClangARMSmeBuiltins) +clang_tablegen(arm_sme_builtins.json -gen-arm-sme-builtins-json + SOURCE arm_sme.td + TARGET ClangARMSmeBuiltinsJSON) clang_tablegen(arm_sme_builtin_cg.inc -gen-arm-sme-builtin-codegen SOURCE arm_sme.td TARGET ClangARMSmeBuiltinCG) diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 872f73e..d924cb4 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -306,6 +306,8 @@ CODEGENOPT(SanitizeBinaryMetadataCovered, 1, 0, Benign) ///< Emit PCs for covere CODEGENOPT(SanitizeBinaryMetadataAtomics, 1, 0, Benign) ///< Emit PCs for atomic operations. CODEGENOPT(SanitizeBinaryMetadataUAR, 1, 0, Benign) ///< Emit PCs for start of functions ///< that are subject for use-after-return checking. +CODEGENOPT(SanitizeAllocTokenFastABI, 1, 0, Benign) ///< Use the AllocToken fast ABI. +CODEGENOPT(SanitizeAllocTokenExtended, 1, 0, Benign) ///< Extend coverage to custom allocation functions. CODEGENOPT(SanitizeStats , 1, 0, Benign) ///< Collect statistics for sanitizers. ENUM_CODEGENOPT(SanitizeDebugTrapReasons, SanitizeDebugTrapReasonKind, 2, SanitizeDebugTrapReasonKind::Detailed, Benign) ///< Control how "trap reasons" are emitted in debug info CODEGENOPT(SimplifyLibCalls , 1, 1, Benign) ///< Set when -fbuiltin is enabled. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 5d5cf25..cae06c3 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -447,6 +447,10 @@ public: std::optional<double> AllowRuntimeCheckSkipHotCutoff; + /// Maximum number of allocation tokens (0 = no max), nullopt if none set (use + /// pass default). + std::optional<uint64_t> AllocTokenMax; + /// List of backend command-line options for -fembed-bitcode. std::vector<uint8_t> CmdArgs; diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 0c994e0..4b27a42 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1750,7 +1750,8 @@ def ReadOnlyPlacementChecks : DiagGroup<"read-only-types">; // Warnings and fixes to support the "safe buffers" programming model. def UnsafeBufferUsageInContainer : DiagGroup<"unsafe-buffer-usage-in-container">; def UnsafeBufferUsageInLibcCall : DiagGroup<"unsafe-buffer-usage-in-libc-call">; -def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInContainer, UnsafeBufferUsageInLibcCall]>; +def UnsafeBufferUsageInUniquePtrArrayAccess : DiagGroup<"unsafe-buffer-usage-in-unique-ptr-array-access">; +def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInContainer, UnsafeBufferUsageInLibcCall, UnsafeBufferUsageInUniquePtrArrayAccess]>; // Warnings and notes InstallAPI verification. def InstallAPIViolation : DiagGroup<"installapi-violation">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b157cbb..5be63c0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13295,6 +13295,8 @@ def note_safe_buffer_usage_suggestions_disabled : Note< def warn_unsafe_buffer_usage_in_container : Warning< "the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information">, InGroup<UnsafeBufferUsageInContainer>, DefaultIgnore; +def warn_unsafe_buffer_usage_unique_ptr_array_access : Warning<"direct access using operator[] on std::unique_ptr<T[]> is unsafe due to lack of bounds checking">, + InGroup<UnsafeBufferUsageInUniquePtrArrayAccess>, DefaultIgnore; #ifndef NDEBUG // Not a user-facing diagnostic. Useful for debugging false negatives in // -fsafe-buffer-usage-suggestions (i.e. lack of -Wunsafe-buffer-usage fixits). diff --git a/clang/include/clang/Basic/SanitizerSpecialCaseList.h b/clang/include/clang/Basic/SanitizerSpecialCaseList.h index cf74859..a05da4c 100644 --- a/clang/include/clang/Basic/SanitizerSpecialCaseList.h +++ b/clang/include/clang/Basic/SanitizerSpecialCaseList.h @@ -57,12 +57,10 @@ protected: void createSanitizerSections(); struct SanitizerSection { - SanitizerSection(SanitizerMask SM, SectionEntries &E, unsigned idx) - : Mask(SM), Entries(E), FileIdx(idx) {}; + SanitizerSection(SanitizerMask SM, const Section &S) : Mask(SM), S(S) {}; SanitizerMask Mask; - SectionEntries &Entries; - unsigned FileIdx; + const Section &S; }; std::vector<SanitizerSection> SanitizerSections; diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def index 1d0e97c..da85431 100644 --- a/clang/include/clang/Basic/Sanitizers.def +++ b/clang/include/clang/Basic/Sanitizers.def @@ -195,6 +195,9 @@ SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds) // Scudo hardened allocator SANITIZER("scudo", Scudo) +// AllocToken +SANITIZER("alloc-token", AllocToken) + // Magic group, containing all sanitizers. For example, "-fno-sanitize=all" // can be used to disable all the sanitizers. SANITIZER_GROUP("all", All, ~SanitizerMask()) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 7714750..bb62223 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -602,6 +602,63 @@ def CIR_VTableAttr : CIR_Attr<"VTable", "vtable", [TypedAttrInterface]> { } //===----------------------------------------------------------------------===// +// DynamicCastInfoAttr +//===----------------------------------------------------------------------===// + +def CIR_DynamicCastInfoAttr : CIR_Attr<"DynamicCastInfo", "dyn_cast_info"> { + let summary = "ABI specific information about a dynamic cast"; + let description = [{ + Provide ABI specific information about a dynamic cast operation. + + The `src_rtti` and the `dest_rtti` parameters give the RTTI of the source + record type and the destination record type, respectively. + + The `runtime_func` parameter gives the `__dynamic_cast` function which is + provided by the runtime. The `bad_cast_func` parameter gives the + `__cxa_bad_cast` function which is also provided by the runtime. + + The `offset_hint` parameter gives the hint value that should be passed to + the `__dynamic_cast` runtime function. + }]; + + let parameters = (ins + CIR_GlobalViewAttr:$src_rtti, + CIR_GlobalViewAttr:$dest_rtti, + "mlir::FlatSymbolRefAttr":$runtime_func, + "mlir::FlatSymbolRefAttr":$bad_cast_func, + CIR_IntAttr:$offset_hint + ); + + let builders = [ + AttrBuilderWithInferredContext<(ins + "GlobalViewAttr":$src_rtti, + "GlobalViewAttr":$dest_rtti, + "mlir::FlatSymbolRefAttr":$runtime_func, + "mlir::FlatSymbolRefAttr":$bad_cast_func, + "IntAttr":$offset_hint), [{ + return $_get(src_rtti.getContext(), src_rtti, dest_rtti, runtime_func, + bad_cast_func, offset_hint); + }]>, + ]; + + let genVerifyDecl = 1; + let assemblyFormat = [{ + `<` + struct(qualified($src_rtti), + qualified($dest_rtti), + $runtime_func, + $bad_cast_func, + qualified($offset_hint)) + `>` + }]; + + let extraClassDeclaration = [{ + /// Get attribute alias name for this attribute. + std::string getAlias() const; + }]; +} + +//===----------------------------------------------------------------------===// // TargetAddressSpaceAttr //===----------------------------------------------------------------------===// @@ -713,6 +770,51 @@ def CIR_VisibilityAttr : CIR_EnumAttr<CIR_VisibilityKind, "visibility"> { } //===----------------------------------------------------------------------===// +// GloblCtorAttr +//===----------------------------------------------------------------------===// + +class CIR_GlobalCtorDtor<string name, string attrMnemonic> + : CIR_Attr<"Global" # name, "global_" # attrMnemonic> { + let parameters = (ins "mlir::StringAttr":$name, "int":$priority); + + let skipDefaultBuilders = 1; + let builders = [ + AttrBuilder<(ins + "llvm::StringRef":$name, + CArg<"int", "65535">:$priority), [{ + return $_get($_ctxt, mlir::StringAttr::get($_ctxt, name), priority); + }]>, + AttrBuilderWithInferredContext<(ins + "mlir::StringAttr":$name, + CArg<"int", "65535">:$priority), [{ + return $_get(name.getContext(), name, priority); + }]> + ]; + + let assemblyFormat = [{ + `<` $name `,` $priority `>` + }]; + + let extraClassDeclaration = [{ + bool isDefaultPriority() const { + return getPriority() == getDefaultPriority(); + }; + + static int getDefaultPriority() { + return 65535; + } + }]; +} + +def CIR_GlobalCtorAttr : CIR_GlobalCtorDtor<"Ctor", "ctor"> { + let summary = "Marks a function as a global constructor"; + let description = [{ + Marks the function as a global constructor in the module's constructor list. + It will be executed before main() is called. + }]; +} + +//===----------------------------------------------------------------------===// // BitfieldInfoAttr //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDataLayout.h b/clang/include/clang/CIR/Dialect/IR/CIRDataLayout.h index 417a226..5c6ce7a 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDataLayout.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRDataLayout.h @@ -14,6 +14,7 @@ #include "mlir/Dialect/DLTI/DLTI.h" #include "mlir/IR/BuiltinOps.h" +#include "clang/CIR/Dialect/IR/CIRTypes.h" namespace cir { @@ -81,6 +82,18 @@ public: } llvm::TypeSize getTypeSizeInBits(mlir::Type ty) const; + + llvm::TypeSize getPointerTypeSizeInBits(mlir::Type ty) const { + assert(mlir::isa<cir::PointerType>(ty) && + "This should only be called with a pointer type"); + return layout.getTypeSizeInBits(ty); + } + + mlir::Type getIntPtrType(mlir::Type ty) const { + assert(mlir::isa<cir::PointerType>(ty) && "Expected pointer type"); + return cir::IntType::get(ty.getContext(), getPointerTypeSizeInBits(ty), + false); + } }; } // namespace cir diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td index 15d5fa0..feb08d60 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td @@ -42,6 +42,7 @@ def CIR_Dialect : Dialect { static llvm::StringRef getNoThrowAttrName() { return "nothrow"; } static llvm::StringRef getSideEffectAttrName() { return "side_effect"; } static llvm::StringRef getModuleLevelAsmAttrName() { return "cir.module_asm"; } + static llvm::StringRef getGlobalCtorsAttrName() { return "cir.global_ctors"; } void registerAttributes(); void registerTypes(); diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index d4ffcf3..27fe0cc 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -232,6 +232,100 @@ def CIR_CastOp : CIR_Op<"cast", [ }]; } +//===----------------------------------------------------------------------===// +// DynamicCastOp +//===----------------------------------------------------------------------===// + +def CIR_DynamicCastKind : CIR_I32EnumAttr< + "DynamicCastKind", "dynamic cast kind", [ + I32EnumAttrCase<"Ptr", 0, "ptr">, + I32EnumAttrCase<"Ref", 1, "ref"> +]>; + +def CIR_DynamicCastOp : CIR_Op<"dyn_cast"> { + let summary = "Perform dynamic cast on record pointers"; + let description = [{ + The `cir.dyn_cast` operation models part of the semantics of the + `dynamic_cast` operator in C++. It can be used to perform 3 kinds of casts + on record pointers: + + - Down-cast, which casts a base class pointer to a derived class pointer; + - Side-cast, which casts a class pointer to a sibling class pointer; + - Cast-to-complete, which casts a class pointer to a void pointer. + + The input of the operation must be a record pointer. The result of the + operation is either a record pointer or a void pointer. + + The parameter `kind` specifies the semantics of this operation. If its value + is `ptr`, then the operation models dynamic casts on pointers. Otherwise, if + its value is `ref`, the operation models dynamic casts on references. + Specifically: + + - When the input pointer is a null pointer value: + - If `kind` is `ref`, the operation will invoke undefined behavior. A + sanitizer check will be emitted if sanitizer is on. + - Otherwise, the operation will return a null pointer value as its result. + - When the runtime type check fails: + - If `kind` is `ref`, the operation will throw a `bad_cast` exception. + - Otherwise, the operation will return a null pointer value as its result. + + The `info` argument gives detailed information about the requested dynamic + cast operation. It is an optional `#cir.dyn_cast_info` attribute that is + only present when the operation models a down-cast or a side-cast. + + The `relative_layout` argument specifies whether the Itanium C++ ABI vtable + uses relative layout. It is only meaningful when the operation models a + cast-to-complete operation. + + Examples: + + ```mlir + %0 = cir.dyn_cast ptr %p : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived> + %1 = cir.dyn_cast ptr relative_layout %p : !cir.ptr<!rec_Base> + -> !cir.ptr<!rec_Derived> + %2 = cir.dyn_cast ref %r : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived> + #cir.dyn_cast_info< + srcRtti = #cir.global_view<@_ZTI4Base> : !cir.ptr<!u8i>, + destRtti = #cir.global_view<@_ZTI7Derived> : !cir.ptr<!u8i>, + runtimeFunc = @__dynamic_cast, + badCastFunc = @__cxa_bad_cast, + offsetHint = #cir.int<0> : !s64i + > + ``` + }]; + + let arguments = (ins + CIR_DynamicCastKind:$kind, + CIR_PtrToRecordType:$src, + OptionalAttr<CIR_DynamicCastInfoAttr>:$info, + UnitAttr:$relative_layout + ); + + let results = (outs + CIR_PtrToAnyOf<[CIR_VoidType, CIR_RecordType]>:$result + ); + + let assemblyFormat = [{ + $kind (`relative_layout` $relative_layout^)? $src + `:` qualified(type($src)) `->` qualified(type($result)) + (qualified($info)^)? attr-dict + }]; + + let extraClassDeclaration = [{ + /// Determine whether this operation models reference casting in C++. + bool isRefCast() { + return getKind() == ::cir::DynamicCastKind::Ref; + } + + /// Determine whether this operation represents a dynamic cast to a void + /// pointer. + bool isCastToVoid() { + return getType().isVoidPtr(); + } + }]; + + let hasLLVMLowering = false; +} //===----------------------------------------------------------------------===// // PtrStrideOp @@ -278,22 +372,22 @@ def CIR_PtrStrideOp : CIR_Op<"ptr_stride", [ def CIR_ConstantOp : CIR_Op<"const", [ ConstantLike, Pure, AllTypesMatch<["value", "res"]> ]> { - let summary = "Defines a CIR constant"; + let summary = "Create a CIR constant from a literal attribute"; let description = [{ The `cir.const` operation turns a literal into an SSA value. The data is attached to the operation as an attribute. ```mlir - %0 = cir.const 42 : i32 - %1 = cir.const 4.2 : f32 - %2 = cir.const nullptr : !cir.ptr<i32> + %0 = cir.const #cir.int<4> : !u32i + %1 = cir.const #cir.fp<1.500000e+00> : !cir.float + %2 = cir.const #cir.ptr<null> : !cir.ptr<!void> ``` }]; let arguments = (ins TypedAttrInterface:$value); let results = (outs CIR_AnyType:$res); - let assemblyFormat = "attr-dict $value"; + let assemblyFormat = "$value attr-dict"; let hasVerifier = 1; @@ -3277,9 +3371,9 @@ def CIR_ComplexCreateOp : CIR_Op<"complex.create", [Pure, SameTypeOperands]> { def CIR_ComplexRealOp : CIR_Op<"complex.real", [Pure]> { let summary = "Extract the real part of a complex value"; let description = [{ - `cir.complex.real` operation takes an operand of `!cir.complex`, `!cir.int` - or `!cir.float`. If the operand is `!cir.complex`, the real part of it will - be returned, otherwise the value returned unmodified. + `cir.complex.real` operation takes an operand of `!cir.complex`, `cir.int`, + `!cir.bool` or `!cir.float`. If the operand is `!cir.complex`, the real + part of it will be returned, otherwise the value returned unmodified. Example: @@ -3289,8 +3383,8 @@ def CIR_ComplexRealOp : CIR_Op<"complex.real", [Pure]> { ``` }]; - let results = (outs CIR_AnyIntOrFloatType:$result); - let arguments = (ins CIR_AnyComplexOrIntOrFloatType:$operand); + let results = (outs CIR_AnyIntOrBoolOrFloatType:$result); + let arguments = (ins CIR_AnyComplexOrIntOrBoolOrFloatType:$operand); let assemblyFormat = [{ $operand `:` qualified(type($operand)) `->` qualified(type($result)) @@ -3309,8 +3403,8 @@ def CIR_ComplexImagOp : CIR_Op<"complex.imag", [Pure]> { let summary = "Extract the imaginary part of a complex value"; let description = [{ `cir.complex.imag` operation takes an operand of `!cir.complex`, `!cir.int` - or `!cir.float`. If the operand is `!cir.complex`, the imag part of it will - be returned, otherwise a zero value will be returned. + `!cir.bool` or `!cir.float`. If the operand is `!cir.complex`, the imag + part of it will be returned, otherwise a zero value will be returned. Example: @@ -3320,8 +3414,8 @@ def CIR_ComplexImagOp : CIR_Op<"complex.imag", [Pure]> { ``` }]; - let results = (outs CIR_AnyIntOrFloatType:$result); - let arguments = (ins CIR_AnyComplexOrIntOrFloatType:$operand); + let results = (outs CIR_AnyIntOrBoolOrFloatType:$result); + let arguments = (ins CIR_AnyComplexOrIntOrBoolOrFloatType:$operand); let assemblyFormat = [{ $operand `:` qualified(type($operand)) `->` qualified(type($result)) @@ -4169,6 +4263,40 @@ def CIR_ThrowOp : CIR_Op<"throw"> { } //===----------------------------------------------------------------------===// +// AllocExceptionOp +//===----------------------------------------------------------------------===// + +def CIR_AllocExceptionOp : CIR_Op<"alloc.exception"> { + let summary = "Allocates an exception according to Itanium ABI"; + let description = [{ + Implements a slightly higher level __cxa_allocate_exception: + + `void *__cxa_allocate_exception(size_t thrown_size);` + + If the operation fails, the program terminates rather than throw. + + Example: + + ```mlir + // if (b == 0) { + // ... + // throw "..."; + cir.if %10 { + %11 = cir.alloc_exception 8 -> !cir.ptr<!void> + ... // store exception content into %11 + cir.throw %11 : !cir.ptr<!cir.ptr<!u8i>>, ... + ``` + }]; + + let arguments = (ins I64Attr:$size); + let results = (outs Res<CIR_PointerType, "", [MemAlloc<DefaultResource>]>:$addr); + + let assemblyFormat = [{ + $size `->` qualified(type($addr)) attr-dict + }]; +} + +//===----------------------------------------------------------------------===// // Atomic operations //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td index da03a29..b2c146c 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td @@ -159,19 +159,31 @@ def CIR_AnyIntOrFloatType : AnyTypeOf<[CIR_AnyFloatType, CIR_AnyIntType], let cppFunctionName = "isAnyIntegerOrFloatingPointType"; } +def CIR_AnyIntOrBoolOrFloatType + : AnyTypeOf<[CIR_AnyBoolType, CIR_AnyFloatType, CIR_AnyIntType], + "integer, boolean or floating point type"> { + let cppFunctionName = "isAnyIntegerOrBooleanOrFloatingPointType"; +} + //===----------------------------------------------------------------------===// // Complex Type predicates //===----------------------------------------------------------------------===// def CIR_AnyComplexType : CIR_TypeBase<"::cir::ComplexType", "complex type">; -def CIR_AnyComplexOrIntOrFloatType : AnyTypeOf<[ - CIR_AnyComplexType, CIR_AnyFloatType, CIR_AnyIntType -], "complex, integer or floating point type"> { - let cppFunctionName = "isComplexOrIntegerOrFloatingPointType"; +def CIR_AnyComplexOrIntOrBoolOrFloatType + : AnyTypeOf<[CIR_AnyComplexType, CIR_AnyIntOrBoolOrFloatType], + "complex, integer or floating point type"> { + let cppFunctionName = "isComplexOrIntegerOrBoolOrFloatingPointType"; } //===----------------------------------------------------------------------===// +// Record Type predicates +//===----------------------------------------------------------------------===// + +def CIR_AnyRecordType : CIR_TypeBase<"::cir::RecordType", "record type">; + +//===----------------------------------------------------------------------===// // Array Type predicates //===----------------------------------------------------------------------===// @@ -228,6 +240,8 @@ def CIR_PtrToIntOrFloatType : CIR_PtrToType<CIR_AnyIntOrFloatType>; def CIR_PtrToComplexType : CIR_PtrToType<CIR_AnyComplexType>; +def CIR_PtrToRecordType : CIR_PtrToType<CIR_AnyRecordType>; + def CIR_PtrToArray : CIR_PtrToType<CIR_AnyArrayType>; //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index f795800..3b7b130 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -39,7 +39,6 @@ struct MissingFeatures { static bool opGlobalUsedOrCompilerUsed() { return false; } static bool opGlobalAnnotations() { return false; } static bool opGlobalDtorLowering() { return false; } - static bool opGlobalCtorAttr() { return false; } static bool opGlobalCtorPriority() { return false; } static bool opGlobalCtorList() { return false; } static bool setDSOLocal() { return false; } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 60c4ad4..ec38231 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2731,8 +2731,25 @@ def fsanitize_skip_hot_cutoff_EQ "(0.0 [default] = skip none; 1.0 = skip all). " "Argument format: <sanitizer1>=<value1>,<sanitizer2>=<value2>,...">; +defm sanitize_alloc_token_fast_abi : BoolOption<"f", "sanitize-alloc-token-fast-abi", + CodeGenOpts<"SanitizeAllocTokenFastABI">, DefaultFalse, + PosFlag<SetTrue, [], [ClangOption], "Use the AllocToken fast ABI">, + NegFlag<SetFalse, [], [ClangOption], "Use the default AllocToken ABI">>, + Group<f_clang_Group>; +defm sanitize_alloc_token_extended : BoolOption<"f", "sanitize-alloc-token-extended", + CodeGenOpts<"SanitizeAllocTokenExtended">, DefaultFalse, + PosFlag<SetTrue, [], [ClangOption], "Enable">, + NegFlag<SetFalse, [], [ClangOption], "Disable">, + BothFlags<[], [ClangOption], " extended coverage to custom allocation functions">>, + Group<f_clang_Group>; + } // end -f[no-]sanitize* flags +def falloc_token_max_EQ : Joined<["-"], "falloc-token-max=">, + Group<f_Group>, Visibility<[ClangOption, CC1Option]>, + MetaVarName<"<N>">, + HelpText<"Limit to maximum N allocation tokens (0 = no max)">; + def fallow_runtime_check_skip_hot_cutoff_EQ : Joined<["-"], "fallow-runtime-check-skip-hot-cutoff=">, Group<f_clang_Group>, @@ -4715,6 +4732,10 @@ def gdwarf_4 : Flag<["-"], "gdwarf-4">, Group<g_Group>, HelpText<"Generate source-level debug information with dwarf version 4">; def gdwarf_5 : Flag<["-"], "gdwarf-5">, Group<g_Group>, HelpText<"Generate source-level debug information with dwarf version 5">; +def gdwarf_6 + : Flag<["-"], "gdwarf-6">, + Group<g_Group>, + HelpText<"Generate source-level debug information with dwarf version 6">; } def gdwarf64 : Flag<["-"], "gdwarf64">, Group<g_Group>, Visibility<[ClangOption, CC1Option, CC1AsOption]>, diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h index 2b72268..eea7897 100644 --- a/clang/include/clang/Driver/SanitizerArgs.h +++ b/clang/include/clang/Driver/SanitizerArgs.h @@ -75,6 +75,8 @@ class SanitizerArgs { llvm::AsanDetectStackUseAfterReturnMode::Invalid; std::string MemtagMode; + bool AllocTokenFastABI = false; + bool AllocTokenExtended = false; public: /// Parses the sanitizer arguments from an argument list. diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index d34a414..59bbd0f 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -1202,12 +1202,12 @@ class Sema; /// Would use of this function result in a rewrite using a different /// operator? - bool isRewrittenOperator(const FunctionDecl *FD) { + bool isRewrittenOperator(const FunctionDecl *FD) const { return OriginalOperator && FD->getDeclName().getCXXOverloadedOperator() != OriginalOperator; } - bool isAcceptableCandidate(const FunctionDecl *FD) { + bool isAcceptableCandidate(const FunctionDecl *FD) const { if (!OriginalOperator) return true; @@ -1234,7 +1234,7 @@ class Sema; } /// Determines whether this operator could be implemented by a function /// with reversed parameter order. - bool isReversible() { + bool isReversible() const { return AllowRewrittenCandidates && OriginalOperator && (getRewrittenOverloadedOperator(OriginalOperator) != OO_None || allowsReversed(OriginalOperator)); @@ -1242,13 +1242,13 @@ class Sema; /// Determine whether reversing parameter order is allowed for operator /// Op. - bool allowsReversed(OverloadedOperatorKind Op); + bool allowsReversed(OverloadedOperatorKind Op) const; /// Determine whether we should add a rewritten candidate for \p FD with /// reversed parameter order. /// \param OriginalArgs are the original non reversed arguments. bool shouldAddReversed(Sema &S, ArrayRef<Expr *> OriginalArgs, - FunctionDecl *FD); + FunctionDecl *FD) const; }; private: |