diff options
| author | Michael Kruse <llvm-project@meinersbur.de> | 2025-01-03 10:22:51 +0100 |
|---|---|---|
| committer | Michael Kruse <llvm-project@meinersbur.de> | 2025-01-03 10:22:51 +0100 |
| commit | 38500d63e14ce340236840f60d356cdefb56a52c (patch) | |
| tree | 17edbec446ce9b50d2f215a483b83afb293a635d /clang/include | |
| parent | 1a3d5daaef7a6a63448a497da3eff7fc9e23df26 (diff) | |
| parent | 27f30029741ecf023baece7b3dde1ff9011ffefc (diff) | |
Merge branch 'main' into users/meinersbur/flang_runtime_split-headersusers/meinersbur/flang_runtime_split-headers
Diffstat (limited to 'clang/include')
95 files changed, 2509 insertions, 412 deletions
diff --git a/clang/include/clang-c/CXString.h b/clang/include/clang-c/CXString.h index f117010c71a4..63dce4d140ce 100644 --- a/clang/include/clang-c/CXString.h +++ b/clang/include/clang-c/CXString.h @@ -46,6 +46,10 @@ typedef struct { /** * Retrieve the character data associated with the given string. + * + * The returned data is a reference and not owned by the user. This data + * is only valid while the `CXString` is valid. This function is similar + * to `std::string::c_str()`. */ CINDEX_LINKAGE const char *clang_getCString(CXString string); diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 8fc06328f0bc..dfc562da88af 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2166,9 +2166,39 @@ enum CXCursorKind { */ CXCursor_OpenACCLoopConstruct = 321, + /** OpenACC Combined Constructs. + */ CXCursor_OpenACCCombinedConstruct = 322, - CXCursor_LastStmt = CXCursor_OpenACCCombinedConstruct, + /** OpenACC data Construct. + */ + CXCursor_OpenACCDataConstruct = 323, + + /** OpenACC enter data Construct. + */ + CXCursor_OpenACCEnterDataConstruct = 324, + + /** OpenACC exit data Construct. + */ + CXCursor_OpenACCExitDataConstruct = 325, + + /** OpenACC host_data Construct. + */ + CXCursor_OpenACCHostDataConstruct = 326, + + /** OpenACC wait Construct. + */ + CXCursor_OpenACCWaitConstruct = 327, + + /** OpenACC init Construct. + */ + CXCursor_OpenACCInitConstruct = 328, + + /** OpenACC shutdown Construct. + */ + CXCursor_OpenACCShutdownConstruct = 329, + + CXCursor_LastStmt = CXCursor_OpenACCShutdownConstruct, /** * Cursor that represents the translation unit itself. diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index ff374ad3ada0..9c01978fd49e 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -542,6 +542,9 @@ public: /// The result type of this function, as a C type. std::string ResultType; + /// Ownership convention for return value + std::string SwiftReturnOwnership; + /// The function parameters. std::vector<ParamInfo> Params; @@ -622,7 +625,8 @@ inline bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS) { LHS.NumAdjustedNullable == RHS.NumAdjustedNullable && LHS.NullabilityPayload == RHS.NullabilityPayload && LHS.ResultType == RHS.ResultType && LHS.Params == RHS.Params && - LHS.RawRetainCountConvention == RHS.RawRetainCountConvention; + LHS.RawRetainCountConvention == RHS.RawRetainCountConvention && + LHS.SwiftReturnOwnership == RHS.SwiftReturnOwnership; } inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) { diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index 7869ee386689..4401f3a8ff48 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -157,11 +157,9 @@ public: void Profile(llvm::FoldingSetNodeID &ID) const; - template <class T> - bool is() const { return Ptr.is<T>(); } + template <class T> bool is() const { return isa<T>(Ptr); } - template <class T> - T get() const { return Ptr.get<T>(); } + template <class T> T get() const { return cast<T>(Ptr); } template <class T> T dyn_cast() const { return Ptr.dyn_cast<T>(); } diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 89fcb6789d88..1e89a6805ce9 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -245,7 +245,11 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; mutable llvm::FoldingSet<DependentUnaryTransformType> DependentUnaryTransformTypes; - mutable llvm::ContextualFoldingSet<AutoType, ASTContext&> AutoTypes; + // An AutoType can have a dependency on another AutoType via its template + // arguments. Since both dependent and dependency are on the same set, + // we can end up in an infinite recursion when looking for a node if we used + // a `FoldingSet`, since both could end up in the same bucket. + mutable llvm::DenseMap<llvm::FoldingSetNodeID, AutoType *> AutoTypes; mutable llvm::FoldingSet<DeducedTemplateSpecializationType> DeducedTemplateSpecializationTypes; mutable llvm::FoldingSet<AtomicType> AtomicTypes; diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 3d63d581a9be..f5652b295de1 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -159,7 +159,7 @@ public: // Some statements have custom mechanisms for dumping their children. if (isa<DeclStmt>(S) || isa<GenericSelectionExpr>(S) || - isa<RequiresExpr>(S)) + isa<RequiresExpr>(S) || isa<OpenACCWaitConstruct>(S)) return; if (Traversal == TK_IgnoreUnlessSpelledInSource && @@ -825,6 +825,16 @@ public: Visit(C); } + void VisitOpenACCWaitConstruct(const OpenACCWaitConstruct *Node) { + // Needs custom child checking to put clauses AFTER the children, which are + // the expressions in the 'wait' construct. Others likely need this as well, + // and might need to do the associated statement after it. + for (const Stmt *S : Node->children()) + Visit(S); + for (const auto *C : Node->clauses()) + Visit(C); + } + void VisitInitListExpr(const InitListExpr *ILE) { if (auto *Filler = ILE->getArrayFiller()) { Visit(Filler, "array_filler"); diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index 725498e132fc..3365ebe4d901 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -24,6 +24,7 @@ #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/Sanitizers.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Support/Compiler.h" #include "llvm/Frontend/HLSL/HLSLResource.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/ErrorHandling.h" diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 8c39ef3d5a9f..67ee0bb41269 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -747,9 +747,9 @@ class DeclaratorDecl : public ValueDecl { /// ignoring outer template declarations. SourceLocation InnerLocStart; - bool hasExtInfo() const { return DeclInfo.is<ExtInfo*>(); } - ExtInfo *getExtInfo() { return DeclInfo.get<ExtInfo*>(); } - const ExtInfo *getExtInfo() const { return DeclInfo.get<ExtInfo*>(); } + bool hasExtInfo() const { return isa<ExtInfo *>(DeclInfo); } + ExtInfo *getExtInfo() { return cast<ExtInfo *>(DeclInfo); } + const ExtInfo *getExtInfo() const { return cast<ExtInfo *>(DeclInfo); } protected: DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L, @@ -762,9 +762,8 @@ public: friend class ASTDeclWriter; TypeSourceInfo *getTypeSourceInfo() const { - return hasExtInfo() - ? getExtInfo()->TInfo - : DeclInfo.get<TypeSourceInfo*>(); + return hasExtInfo() ? getExtInfo()->TInfo + : cast<TypeSourceInfo *>(DeclInfo); } void setTypeSourceInfo(TypeSourceInfo *TI) { @@ -3458,18 +3457,17 @@ public: using redeclarable_base::isFirstDecl; bool isModed() const { - return MaybeModedTInfo.getPointer().is<ModedTInfo *>(); + return isa<ModedTInfo *>(MaybeModedTInfo.getPointer()); } TypeSourceInfo *getTypeSourceInfo() const { - return isModed() ? MaybeModedTInfo.getPointer().get<ModedTInfo *>()->first - : MaybeModedTInfo.getPointer().get<TypeSourceInfo *>(); + return isModed() ? cast<ModedTInfo *>(MaybeModedTInfo.getPointer())->first + : cast<TypeSourceInfo *>(MaybeModedTInfo.getPointer()); } QualType getUnderlyingType() const { - return isModed() ? MaybeModedTInfo.getPointer().get<ModedTInfo *>()->second - : MaybeModedTInfo.getPointer() - .get<TypeSourceInfo *>() + return isModed() ? cast<ModedTInfo *>(MaybeModedTInfo.getPointer())->second + : cast<TypeSourceInfo *>(MaybeModedTInfo.getPointer()) ->getType(); } @@ -3587,10 +3585,10 @@ private: /// otherwise, it is a null (TypedefNameDecl) pointer. llvm::PointerUnion<TypedefNameDecl *, ExtInfo *> TypedefNameDeclOrQualifier; - bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo *>(); } - ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo *>(); } + bool hasExtInfo() const { return isa<ExtInfo *>(TypedefNameDeclOrQualifier); } + ExtInfo *getExtInfo() { return cast<ExtInfo *>(TypedefNameDeclOrQualifier); } const ExtInfo *getExtInfo() const { - return TypedefNameDeclOrQualifier.get<ExtInfo *>(); + return cast<ExtInfo *>(TypedefNameDeclOrQualifier); } protected: @@ -3793,7 +3791,7 @@ public: TypedefNameDecl *getTypedefNameForAnonDecl() const { return hasExtInfo() ? nullptr - : TypedefNameDeclOrQualifier.get<TypedefNameDecl *>(); + : cast<TypedefNameDecl *>(TypedefNameDeclOrQualifier); } void setTypedefNameForAnonDecl(TypedefNameDecl *TDD); @@ -4011,7 +4009,7 @@ public: return QualType(); if (const Type *T = IntegerType.dyn_cast<const Type*>()) return QualType(T, 0); - return IntegerType.get<TypeSourceInfo*>()->getType().getUnqualifiedType(); + return cast<TypeSourceInfo *>(IntegerType)->getType().getUnqualifiedType(); } /// Set the underlying integer type. diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index a3447d199097..82932e098c86 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -271,16 +271,12 @@ private: /// // LexicalDC == global namespace llvm::PointerUnion<DeclContext*, MultipleDC*> DeclCtx; - bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); } - bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); } + bool isInSemaDC() const { return isa<DeclContext *>(DeclCtx); } + bool isOutOfSemaDC() const { return isa<MultipleDC *>(DeclCtx); } - MultipleDC *getMultipleDC() const { - return DeclCtx.get<MultipleDC*>(); - } + MultipleDC *getMultipleDC() const { return cast<MultipleDC *>(DeclCtx); } - DeclContext *getSemanticDC() const { - return DeclCtx.get<DeclContext*>(); - } + DeclContext *getSemanticDC() const { return cast<DeclContext *>(DeclCtx); } /// Loc - The location of this decl. SourceLocation Loc; @@ -1340,7 +1336,7 @@ public: assert(Ptr && "dereferencing end() iterator"); if (DeclListNode *CurNode = Ptr.dyn_cast<DeclListNode*>()) return CurNode->D; - return Ptr.get<NamedDecl*>(); + return cast<NamedDecl *>(Ptr); } void operator->() const { } // Unsupported. bool operator==(const iterator &X) const { return Ptr == X.Ptr; } diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index e389b5cd6df5..c232556edeff 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2388,19 +2388,19 @@ public: /// Determine whether this initializer is initializing a base class. bool isBaseInitializer() const { - return Initializee.is<TypeSourceInfo*>() && !IsDelegating; + return isa<TypeSourceInfo *>(Initializee) && !IsDelegating; } /// Determine whether this initializer is initializing a non-static /// data member. - bool isMemberInitializer() const { return Initializee.is<FieldDecl*>(); } + bool isMemberInitializer() const { return isa<FieldDecl *>(Initializee); } bool isAnyMemberInitializer() const { return isMemberInitializer() || isIndirectMemberInitializer(); } bool isIndirectMemberInitializer() const { - return Initializee.is<IndirectFieldDecl*>(); + return isa<IndirectFieldDecl *>(Initializee); } /// Determine whether this initializer is an implicit initializer @@ -2416,7 +2416,7 @@ public: /// Determine whether this initializer is creating a delegating /// constructor. bool isDelegatingInitializer() const { - return Initializee.is<TypeSourceInfo*>() && IsDelegating; + return isa<TypeSourceInfo *>(Initializee) && IsDelegating; } /// Determine whether this initializer is a pack expansion. @@ -2457,21 +2457,21 @@ public: /// non-static data member being initialized. Otherwise, returns null. FieldDecl *getMember() const { if (isMemberInitializer()) - return Initializee.get<FieldDecl*>(); + return cast<FieldDecl *>(Initializee); return nullptr; } FieldDecl *getAnyMember() const { if (isMemberInitializer()) - return Initializee.get<FieldDecl*>(); + return cast<FieldDecl *>(Initializee); if (isIndirectMemberInitializer()) - return Initializee.get<IndirectFieldDecl*>()->getAnonField(); + return cast<IndirectFieldDecl *>(Initializee)->getAnonField(); return nullptr; } IndirectFieldDecl *getIndirectMember() const { if (isIndirectMemberInitializer()) - return Initializee.get<IndirectFieldDecl*>(); + return cast<IndirectFieldDecl *>(Initializee); return nullptr; } diff --git a/clang/include/clang/AST/DeclContextInternals.h b/clang/include/clang/AST/DeclContextInternals.h index e169c4859219..b17b7627ac90 100644 --- a/clang/include/clang/AST/DeclContextInternals.h +++ b/clang/include/clang/AST/DeclContextInternals.h @@ -70,7 +70,7 @@ class StoredDeclsList { // want to keep (if any) will be of the form DeclListNode(D, <rest>); // replace it with just D. if (NewLast) { - DeclListNode *Node = NewLast->get<DeclListNode*>(); + DeclListNode *Node = cast<DeclListNode *>(*NewLast); *NewLast = Node->D; C.DeallocateDeclListNode(Node); } @@ -84,11 +84,11 @@ class StoredDeclsList { if (!Data.getPointer()) // All declarations are erased. return nullptr; - else if (NewHead.is<NamedDecl *>()) + else if (isa<NamedDecl *>(NewHead)) // The list only contains a declaration, the header itself. return (DeclListNode::Decls *)&Data; else { - assert(NewLast && NewLast->is<NamedDecl *>() && "Not the tail?"); + assert(NewLast && isa<NamedDecl *>(*NewLast) && "Not the tail?"); return NewLast; } } @@ -207,7 +207,7 @@ public: } // Append the Decls. - DeclListNode *Node = C.AllocateDeclListNode(Tail->get<NamedDecl *>()); + DeclListNode *Node = C.AllocateDeclListNode(cast<NamedDecl *>(*Tail)); Node->Rest = DeclsAsList; *Tail = Node; } @@ -293,7 +293,7 @@ public: llvm::errs() << '[' << Node->D << "] -> "; D = Node->Rest; } else { - llvm::errs() << '[' << D.get<NamedDecl*>() << "]\n"; + llvm::errs() << '[' << cast<NamedDecl *>(D) << "]\n"; return; } } diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index e4bf54c3d77b..d3a466a8617b 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -319,8 +319,7 @@ class DefaultArgStorage { const DefaultArgStorage &Storage = Parm->getDefaultArgStorage(); if (auto *Prev = Storage.ValueOrInherited.template dyn_cast<ParmDecl *>()) Parm = Prev; - assert(!Parm->getDefaultArgStorage() - .ValueOrInherited.template is<ParmDecl *>() && + assert(!isa<ParmDecl *>(Parm->getDefaultArgStorage().ValueOrInherited) && "should only be one level of indirection"); return Parm; } @@ -333,7 +332,7 @@ public: /// Determine whether the default argument for this parameter was inherited /// from a previous declaration of the same entity. - bool isInherited() const { return ValueOrInherited.template is<ParmDecl*>(); } + bool isInherited() const { return isa<ParmDecl *>(ValueOrInherited); } /// Get the default argument's value. This does not consider whether the /// default argument is visible. @@ -343,7 +342,7 @@ public: Storage = &Prev->getDefaultArgStorage(); if (const auto *C = Storage->ValueOrInherited.template dyn_cast<Chain *>()) return C->Value; - return Storage->ValueOrInherited.template get<ArgType>(); + return cast<ArgType>(Storage->ValueOrInherited); } /// Get the parameter from which we inherit the default argument, if any. @@ -379,7 +378,7 @@ public: Inherited->PrevDeclWithDefaultArg = InheritedFrom; } else ValueOrInherited = new (allocateDefaultArgStorageChain(C)) - Chain{InheritedFrom, ValueOrInherited.template get<ArgType>()}; + Chain{InheritedFrom, cast<ArgType>(ValueOrInherited)}; } /// Remove the default argument, even if it was inherited. @@ -735,6 +734,7 @@ class RedeclarableTemplateDecl : public TemplateDecl, } void anchor() override; + protected: template <typename EntryType> struct SpecEntryTraits { using DeclType = EntryType; @@ -775,13 +775,22 @@ protected: return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin()); } - void loadLazySpecializationsImpl() const; + void loadLazySpecializationsImpl(bool OnlyPartial = false) const; + + bool loadLazySpecializationsImpl(llvm::ArrayRef<TemplateArgument> Args, + TemplateParameterList *TPL = nullptr) const; template <class EntryType, typename ...ProfileArguments> typename SpecEntryTraits<EntryType>::DeclType* findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs, void *&InsertPos, ProfileArguments &&...ProfileArgs); + template <class EntryType, typename... ProfileArguments> + typename SpecEntryTraits<EntryType>::DeclType * + findSpecializationLocally(llvm::FoldingSetVector<EntryType> &Specs, + void *&InsertPos, + ProfileArguments &&...ProfileArgs); + template <class Derived, class EntryType> void addSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs, EntryType *Entry, void *InsertPos); @@ -796,13 +805,6 @@ protected: /// was explicitly specialized. llvm::PointerIntPair<RedeclarableTemplateDecl *, 1, bool> InstantiatedFromMember; - - /// If non-null, points to an array of specializations (including - /// partial specializations) known only by their external declaration IDs. - /// - /// The first value in the array is the number of specializations/partial - /// specializations that follow. - GlobalDeclID *LazySpecializations = nullptr; }; /// Pointer to the common data shared by all declarations of this @@ -1962,7 +1964,7 @@ public: SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>()) return PartialSpec->PartialSpecialization; - return SpecializedTemplate.get<ClassTemplateDecl*>(); + return cast<ClassTemplateDecl *>(SpecializedTemplate); } /// Retrieve the set of template arguments that should be used @@ -1989,7 +1991,7 @@ public: /// template arguments have been deduced. void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec, const TemplateArgumentList *TemplateArgs) { - assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() && + assert(!isa<SpecializedPartialSpecialization *>(SpecializedTemplate) && "Already set to a class template partial specialization!"); auto *PS = new (getASTContext()) SpecializedPartialSpecialization(); PS->PartialSpecialization = PartialSpec; @@ -2000,7 +2002,7 @@ public: /// Note that this class template specialization is an instantiation /// of the given class template. void setInstantiationOf(ClassTemplateDecl *TemplDecl) { - assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() && + assert(!isa<SpecializedPartialSpecialization *>(SpecializedTemplate) && "Previously set to a class template partial specialization!"); SpecializedTemplate = TemplDecl; } @@ -2010,7 +2012,7 @@ public: const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) return Info->TemplateArgsAsWritten; - return ExplicitInfo.get<const ASTTemplateArgumentListInfo *>(); + return cast<const ASTTemplateArgumentListInfo *>(ExplicitInfo); } /// Set the template argument list as written in the sources. @@ -2283,7 +2285,7 @@ public: friend class TemplateDeclInstantiator; /// Load any lazily-loaded specializations from the external source. - void LoadLazySpecializations() const; + void LoadLazySpecializations(bool OnlyPartial = false) const; /// Get the underlying class declarations of the template. CXXRecordDecl *getTemplatedDecl() const { @@ -2731,7 +2733,7 @@ public: SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>()) return PartialSpec->PartialSpecialization; - return SpecializedTemplate.get<VarTemplateDecl *>(); + return cast<VarTemplateDecl *>(SpecializedTemplate); } /// Retrieve the set of template arguments that should be used @@ -2758,7 +2760,7 @@ public: /// template arguments have been deduced. void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec, const TemplateArgumentList *TemplateArgs) { - assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() && + assert(!isa<SpecializedPartialSpecialization *>(SpecializedTemplate) && "Already set to a variable template partial specialization!"); auto *PS = new (getASTContext()) SpecializedPartialSpecialization(); PS->PartialSpecialization = PartialSpec; @@ -2769,7 +2771,7 @@ public: /// Note that this variable template specialization is an instantiation /// of the given variable template. void setInstantiationOf(VarTemplateDecl *TemplDecl) { - assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() && + assert(!isa<SpecializedPartialSpecialization *>(SpecializedTemplate) && "Previously set to a variable template partial specialization!"); SpecializedTemplate = TemplDecl; } @@ -2779,7 +2781,7 @@ public: const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) return Info->TemplateArgsAsWritten; - return ExplicitInfo.get<const ASTTemplateArgumentListInfo *>(); + return cast<const ASTTemplateArgumentListInfo *>(ExplicitInfo); } /// Set the template argument list as written in the sources. @@ -3033,7 +3035,7 @@ public: friend class ASTDeclWriter; /// Load any lazily-loaded specializations from the external source. - void LoadLazySpecializations() const; + void LoadLazySpecializations(bool OnlyPartial = false) const; /// Get the underlying variable declarations of the template. VarDecl *getTemplatedDecl() const { @@ -3306,7 +3308,7 @@ inline NamedDecl *getAsNamedDecl(TemplateParameter P) { return PD; if (auto *PD = P.dyn_cast<NonTypeTemplateParmDecl *>()) return PD; - return P.get<TemplateTemplateParmDecl *>(); + return cast<TemplateTemplateParmDecl *>(P); } inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) { diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 1a24b8857674..4cec89c979f7 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -878,7 +878,7 @@ public: /// object. This is not a strong guarantee. bool isMostDerived(const ASTContext &Context) const; - bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } + bool isTypeOperand() const { return isa<TypeSourceInfo *>(Operand); } /// Retrieves the type operand of this typeid() expression after /// various required adjustments (removing reference types, cv-qualifiers). @@ -887,11 +887,11 @@ public: /// Retrieve source information for the type operand. TypeSourceInfo *getTypeOperandSourceInfo() const { assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); - return Operand.get<TypeSourceInfo *>(); + return cast<TypeSourceInfo *>(Operand); } Expr *getExprOperand() const { assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); - return static_cast<Expr*>(Operand.get<Stmt *>()); + return static_cast<Expr *>(cast<Stmt *>(Operand)); } SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } @@ -1093,7 +1093,7 @@ public: Operand = (TypeSourceInfo*)nullptr; } - bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } + bool isTypeOperand() const { return isa<TypeSourceInfo *>(Operand); } /// Retrieves the type operand of this __uuidof() expression after /// various required adjustments (removing reference types, cv-qualifiers). @@ -1102,11 +1102,11 @@ public: /// Retrieve source information for the type operand. TypeSourceInfo *getTypeOperandSourceInfo() const { assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); - return Operand.get<TypeSourceInfo *>(); + return cast<TypeSourceInfo *>(Operand); } Expr *getExprOperand() const { assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)"); - return static_cast<Expr*>(Operand.get<Stmt *>()); + return static_cast<Expr *>(cast<Stmt *>(Operand)); } MSGuidDecl *getGuidDecl() const { return Guid; } @@ -4750,24 +4750,24 @@ public: /// be materialized into a glvalue. Expr *getSubExpr() const { return cast<Expr>( - State.is<Stmt *>() - ? State.get<Stmt *>() - : State.get<LifetimeExtendedTemporaryDecl *>()->getTemporaryExpr()); + isa<Stmt *>(State) + ? cast<Stmt *>(State) + : cast<LifetimeExtendedTemporaryDecl *>(State)->getTemporaryExpr()); } /// Retrieve the storage duration for the materialized temporary. StorageDuration getStorageDuration() const { - return State.is<Stmt *>() ? SD_FullExpression - : State.get<LifetimeExtendedTemporaryDecl *>() + return isa<Stmt *>(State) ? SD_FullExpression + : cast<LifetimeExtendedTemporaryDecl *>(State) ->getStorageDuration(); } /// Get the storage for the constant value of a materialized temporary /// of static storage duration. APValue *getOrCreateValue(bool MayCreate) const { - assert(State.is<LifetimeExtendedTemporaryDecl *>() && + assert(isa<LifetimeExtendedTemporaryDecl *>(State) && "the temporary has not been lifetime extended"); - return State.get<LifetimeExtendedTemporaryDecl *>()->getOrCreateValue( + return cast<LifetimeExtendedTemporaryDecl *>(State)->getOrCreateValue( MayCreate); } @@ -4782,8 +4782,8 @@ public: /// Get the declaration which triggered the lifetime-extension of this /// temporary, if any. ValueDecl *getExtendingDecl() { - return State.is<Stmt *>() ? nullptr - : State.get<LifetimeExtendedTemporaryDecl *>() + return isa<Stmt *>(State) ? nullptr + : cast<LifetimeExtendedTemporaryDecl *>(State) ->getExtendingDecl(); } const ValueDecl *getExtendingDecl() const { @@ -4793,8 +4793,8 @@ public: void setExtendingDecl(ValueDecl *ExtendedBy, unsigned ManglingNumber); unsigned getManglingNumber() const { - return State.is<Stmt *>() ? 0 - : State.get<LifetimeExtendedTemporaryDecl *>() + return isa<Stmt *>(State) ? 0 + : cast<LifetimeExtendedTemporaryDecl *>(State) ->getManglingNumber(); } @@ -4820,17 +4820,17 @@ public: // Iterators child_range children() { - return State.is<Stmt *>() + return isa<Stmt *>(State) ? child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1) - : State.get<LifetimeExtendedTemporaryDecl *>()->childrenExpr(); + : cast<LifetimeExtendedTemporaryDecl *>(State)->childrenExpr(); } const_child_range children() const { - return State.is<Stmt *>() + return isa<Stmt *>(State) ? const_child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1) : const_cast<const LifetimeExtendedTemporaryDecl *>( - State.get<LifetimeExtendedTemporaryDecl *>()) + cast<LifetimeExtendedTemporaryDecl *>(State)) ->childrenExpr(); } }; diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h index f3e32ce39619..f988d40cf73c 100644 --- a/clang/include/clang/AST/ExprConcepts.h +++ b/clang/include/clang/AST/ExprConcepts.h @@ -261,13 +261,13 @@ public: assert(Status == SS_SubstitutionFailure && "Attempted to get substitution diagnostic when there has been no " "substitution failure."); - return Value.get<SubstitutionDiagnostic *>(); + return cast<SubstitutionDiagnostic *>(Value); } TypeSourceInfo *getType() const { assert(!isSubstitutionFailure() && "Attempted to get type when there has been a substitution failure."); - return Value.get<TypeSourceInfo *>(); + return cast<TypeSourceInfo *>(Value); } static bool classof(const Requirement *R) { @@ -329,24 +329,24 @@ public: bool isSubstitutionFailure() const { return !isEmpty() && - TypeConstraintInfo.getPointer().is<SubstitutionDiagnostic *>(); + isa<SubstitutionDiagnostic *>(TypeConstraintInfo.getPointer()); } bool isTypeConstraint() const { return !isEmpty() && - TypeConstraintInfo.getPointer().is<TemplateParameterList *>(); + isa<TemplateParameterList *>(TypeConstraintInfo.getPointer()); } SubstitutionDiagnostic *getSubstitutionDiagnostic() const { assert(isSubstitutionFailure()); - return TypeConstraintInfo.getPointer().get<SubstitutionDiagnostic *>(); + return cast<SubstitutionDiagnostic *>(TypeConstraintInfo.getPointer()); } const TypeConstraint *getTypeConstraint() const; TemplateParameterList *getTypeConstraintTemplateParameterList() const { assert(isTypeConstraint()); - return TypeConstraintInfo.getPointer().get<TemplateParameterList *>(); + return cast<TemplateParameterList *>(TypeConstraintInfo.getPointer()); } }; private: @@ -409,14 +409,14 @@ public: assert(isExprSubstitutionFailure() && "Attempted to get expression substitution diagnostic when there has " "been no expression substitution failure"); - return Value.get<SubstitutionDiagnostic *>(); + return cast<SubstitutionDiagnostic *>(Value); } Expr *getExpr() const { assert(!isExprSubstitutionFailure() && "ExprRequirement has no expression because there has been a " "substitution failure."); - return Value.get<Expr *>(); + return cast<Expr *>(Value); } static bool classof(const Requirement *R) { diff --git a/clang/include/clang/AST/ExprObjC.h b/clang/include/clang/AST/ExprObjC.h index f833916c91aa..1fccc2606958 100644 --- a/clang/include/clang/AST/ExprObjC.h +++ b/clang/include/clang/AST/ExprObjC.h @@ -752,28 +752,24 @@ public: setMethodRefFlag(MethodRef_Setter, val); } - const Expr *getBase() const { - return cast<Expr>(Receiver.get<Stmt*>()); - } - Expr *getBase() { - return cast<Expr>(Receiver.get<Stmt*>()); - } + const Expr *getBase() const { return cast<Expr>(cast<Stmt *>(Receiver)); } + Expr *getBase() { return cast<Expr>(cast<Stmt *>(Receiver)); } SourceLocation getLocation() const { return IdLoc; } SourceLocation getReceiverLocation() const { return ReceiverLoc; } QualType getSuperReceiverType() const { - return QualType(Receiver.get<const Type*>(), 0); + return QualType(cast<const Type *>(Receiver), 0); } ObjCInterfaceDecl *getClassReceiver() const { - return Receiver.get<ObjCInterfaceDecl*>(); + return cast<ObjCInterfaceDecl *>(Receiver); } - bool isObjectReceiver() const { return Receiver.is<Stmt*>(); } - bool isSuperReceiver() const { return Receiver.is<const Type*>(); } - bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); } + bool isObjectReceiver() const { return isa<Stmt *>(Receiver); } + bool isSuperReceiver() const { return isa<const Type *>(Receiver); } + bool isClassReceiver() const { return isa<ObjCInterfaceDecl *>(Receiver); } /// Determine the type of the base, regardless of the kind of receiver. QualType getReceiverType(const ASTContext &ctx) const; @@ -787,7 +783,7 @@ public: // Iterators child_range children() { - if (Receiver.is<Stmt*>()) { + if (isa<Stmt *>(Receiver)) { Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack! return child_range(begin, begin+1); } diff --git a/clang/include/clang/AST/ExternalASTSource.h b/clang/include/clang/AST/ExternalASTSource.h index 582ed7c65f58..4d7ff822fceb 100644 --- a/clang/include/clang/AST/ExternalASTSource.h +++ b/clang/include/clang/AST/ExternalASTSource.h @@ -152,6 +152,21 @@ public: virtual bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); + /// Load all the external specializations for the Decl \param D if \param + /// OnlyPartial is false. Otherwise, load all the external **partial** + /// specializations for the \param D. + /// + /// Return true if any new specializations get loaded. Return false otherwise. + virtual bool LoadExternalSpecializations(const Decl *D, bool OnlyPartial); + + /// Load all the specializations for the Decl \param D with the same template + /// args specified by \param TemplateArgs. + /// + /// Return true if any new specializations get loaded. Return false otherwise. + virtual bool + LoadExternalSpecializations(const Decl *D, + ArrayRef<TemplateArgument> TemplateArgs); + /// Ensures that the table of all visible declarations inside this /// context is up to date. /// @@ -447,9 +462,7 @@ public: : Value(Value) {} /// Forcibly set this pointer (which must be lazy) as needing updates. - void markIncomplete() { - Value.template get<LazyData *>()->LastGeneration = 0; - } + void markIncomplete() { cast<LazyData *>(Value)->LastGeneration = 0; } /// Set the value of this pointer, in the current generation. void set(T NewValue) { @@ -472,14 +485,14 @@ public: } return LazyVal->LastValue; } - return Value.template get<T>(); + return cast<T>(Value); } /// Get the most recently computed value of this pointer without updating it. T getNotUpdated() const { if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) return LazyVal->LastValue; - return Value.template get<T>(); + return cast<T>(Value); } void *getOpaqueValue() { return Value.getOpaqueValue(); } diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 5ad4c336b6c5..b4747c68a1df 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -38,7 +38,7 @@ public: SourceLocation getBeginLoc() const { return Location.getBegin(); } SourceLocation getEndLoc() const { return Location.getEnd(); } - static bool classof(const OpenACCClause *) { return false; } + static bool classof(const OpenACCClause *) { return true; } using child_iterator = StmtIterator; using const_child_iterator = ConstStmtIterator; @@ -76,6 +76,50 @@ public: } }; +// Represents the 'finalize' clause. +class OpenACCFinalizeClause : public OpenACCClause { +protected: + OpenACCFinalizeClause(SourceLocation BeginLoc, SourceLocation EndLoc) + : OpenACCClause(OpenACCClauseKind::Finalize, BeginLoc, EndLoc) {} + +public: + static bool classof(const OpenACCClause *C) { + return C->getClauseKind() == OpenACCClauseKind::Finalize; + } + + static OpenACCFinalizeClause * + Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc); + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +// Represents the 'if_present' clause. +class OpenACCIfPresentClause : public OpenACCClause { +protected: + OpenACCIfPresentClause(SourceLocation BeginLoc, SourceLocation EndLoc) + : OpenACCClause(OpenACCClauseKind::IfPresent, BeginLoc, EndLoc) {} + +public: + static bool classof(const OpenACCClause *C) { + return C->getClauseKind() == OpenACCClauseKind::IfPresent; + } + + static OpenACCIfPresentClause * + Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc); + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + // Represents the 'independent' clause. class OpenACCIndependentClause : public OpenACCClause { protected: @@ -147,8 +191,9 @@ using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>; /// an identifier. The 'asterisk' means 'the rest'. class OpenACCDeviceTypeClause final : public OpenACCClauseWithParams, - public llvm::TrailingObjects<OpenACCDeviceTypeClause, + private llvm::TrailingObjects<OpenACCDeviceTypeClause, DeviceTypeArgument> { + friend TrailingObjects; // Data stored in trailing objects as IdentifierInfo* /SourceLocation pairs. A // nullptr IdentifierInfo* represents an asterisk. unsigned NumArchs; @@ -333,7 +378,8 @@ public: // Represents the 'devnum' and expressions lists for the 'wait' clause. class OpenACCWaitClause final : public OpenACCClauseWithExprs, - public llvm::TrailingObjects<OpenACCWaitClause, Expr *> { + private llvm::TrailingObjects<OpenACCWaitClause, Expr *> { + friend TrailingObjects; SourceLocation QueuesLoc; OpenACCWaitClause(SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc, @@ -375,7 +421,8 @@ public: class OpenACCNumGangsClause final : public OpenACCClauseWithExprs, - public llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> { + private llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> { + friend TrailingObjects; OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef<Expr *> IntExprs, SourceLocation EndLoc) @@ -405,7 +452,8 @@ public: class OpenACCTileClause final : public OpenACCClauseWithExprs, - public llvm::TrailingObjects<OpenACCTileClause, Expr *> { + private llvm::TrailingObjects<OpenACCTileClause, Expr *> { + friend TrailingObjects; OpenACCTileClause(SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef<Expr *> SizeExprs, SourceLocation EndLoc) : OpenACCClauseWithExprs(OpenACCClauseKind::Tile, BeginLoc, LParenLoc, @@ -459,7 +507,8 @@ public: class OpenACCGangClause final : public OpenACCClauseWithExprs, - public llvm::TrailingObjects<OpenACCGangClause, Expr *, OpenACCGangKind> { + private llvm::TrailingObjects<OpenACCGangClause, Expr *, OpenACCGangKind> { + friend TrailingObjects; protected: OpenACCGangClause(SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef<OpenACCGangKind> GangKinds, @@ -483,6 +532,14 @@ public: return {getGangKind(I), getExprs()[I]}; } + bool hasExprOfKind(OpenACCGangKind GK) const { + for (unsigned I = 0; I < getNumExprs(); ++I) { + if (getGangKind(I) == GK) + return true; + } + return false; + } + static OpenACCGangClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef<OpenACCGangKind> GangKinds, @@ -562,6 +619,20 @@ public: SourceLocation EndLoc); }; +class OpenACCDeviceNumClause : public OpenACCClauseWithSingleIntExpr { + OpenACCDeviceNumClause(SourceLocation BeginLoc, SourceLocation LParenLoc, + Expr *IntExpr, SourceLocation EndLoc); + +public: + static bool classof(const OpenACCClause *C) { + return C->getClauseKind() == OpenACCClauseKind::DeviceNum; + } + static OpenACCDeviceNumClause *Create(const ASTContext &C, + SourceLocation BeginLoc, + SourceLocation LParenLoc, Expr *IntExpr, + SourceLocation EndLoc); +}; + /// Represents a 'collapse' clause on a 'loop' construct. This clause takes an /// integer constant expression 'N' that represents how deep to collapse the /// construct. It also takes an optional 'force' tag that permits intervening @@ -606,7 +677,8 @@ public: class OpenACCPrivateClause final : public OpenACCClauseWithVarList, - public llvm::TrailingObjects<OpenACCPrivateClause, Expr *> { + private llvm::TrailingObjects<OpenACCPrivateClause, Expr *> { + friend TrailingObjects; OpenACCPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef<Expr *> VarList, SourceLocation EndLoc) @@ -628,7 +700,8 @@ public: class OpenACCFirstPrivateClause final : public OpenACCClauseWithVarList, - public llvm::TrailingObjects<OpenACCFirstPrivateClause, Expr *> { + private llvm::TrailingObjects<OpenACCFirstPrivateClause, Expr *> { + friend TrailingObjects; OpenACCFirstPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef<Expr *> VarList, SourceLocation EndLoc) @@ -650,7 +723,8 @@ public: class OpenACCDevicePtrClause final : public OpenACCClauseWithVarList, - public llvm::TrailingObjects<OpenACCDevicePtrClause, Expr *> { + private llvm::TrailingObjects<OpenACCDevicePtrClause, Expr *> { + friend TrailingObjects; OpenACCDevicePtrClause(SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef<Expr *> VarList, SourceLocation EndLoc) @@ -672,7 +746,8 @@ public: class OpenACCAttachClause final : public OpenACCClauseWithVarList, - public llvm::TrailingObjects<OpenACCAttachClause, Expr *> { + private llvm::TrailingObjects<OpenACCAttachClause, Expr *> { + friend TrailingObjects; OpenACCAttachClause(SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef<Expr *> VarList, SourceLocation EndLoc) @@ -692,9 +767,79 @@ public: ArrayRef<Expr *> VarList, SourceLocation EndLoc); }; +class OpenACCDetachClause final + : public OpenACCClauseWithVarList, + private llvm::TrailingObjects<OpenACCDetachClause, Expr *> { + friend TrailingObjects; + + OpenACCDetachClause(SourceLocation BeginLoc, SourceLocation LParenLoc, + ArrayRef<Expr *> VarList, SourceLocation EndLoc) + : OpenACCClauseWithVarList(OpenACCClauseKind::Detach, BeginLoc, LParenLoc, + EndLoc) { + std::uninitialized_copy(VarList.begin(), VarList.end(), + getTrailingObjects<Expr *>()); + setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size())); + } + +public: + static bool classof(const OpenACCClause *C) { + return C->getClauseKind() == OpenACCClauseKind::Detach; + } + static OpenACCDetachClause * + Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, + ArrayRef<Expr *> VarList, SourceLocation EndLoc); +}; + +class OpenACCDeleteClause final + : public OpenACCClauseWithVarList, + private llvm::TrailingObjects<OpenACCDeleteClause, Expr *> { + friend TrailingObjects; + + OpenACCDeleteClause(SourceLocation BeginLoc, SourceLocation LParenLoc, + ArrayRef<Expr *> VarList, SourceLocation EndLoc) + : OpenACCClauseWithVarList(OpenACCClauseKind::Delete, BeginLoc, LParenLoc, + EndLoc) { + std::uninitialized_copy(VarList.begin(), VarList.end(), + getTrailingObjects<Expr *>()); + setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size())); + } + +public: + static bool classof(const OpenACCClause *C) { + return C->getClauseKind() == OpenACCClauseKind::Delete; + } + static OpenACCDeleteClause * + Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, + ArrayRef<Expr *> VarList, SourceLocation EndLoc); +}; + +class OpenACCUseDeviceClause final + : public OpenACCClauseWithVarList, + private llvm::TrailingObjects<OpenACCUseDeviceClause, Expr *> { + friend TrailingObjects; + + OpenACCUseDeviceClause(SourceLocation BeginLoc, SourceLocation LParenLoc, + ArrayRef<Expr *> VarList, SourceLocation EndLoc) + : OpenACCClauseWithVarList(OpenACCClauseKind::UseDevice, BeginLoc, + LParenLoc, EndLoc) { + std::uninitialized_copy(VarList.begin(), VarList.end(), + getTrailingObjects<Expr *>()); + setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size())); + } + +public: + static bool classof(const OpenACCClause *C) { + return C->getClauseKind() == OpenACCClauseKind::UseDevice; + } + static OpenACCUseDeviceClause * + Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, + ArrayRef<Expr *> VarList, SourceLocation EndLoc); +}; + class OpenACCNoCreateClause final : public OpenACCClauseWithVarList, - public llvm::TrailingObjects<OpenACCNoCreateClause, Expr *> { + private llvm::TrailingObjects<OpenACCNoCreateClause, Expr *> { + friend TrailingObjects; OpenACCNoCreateClause(SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef<Expr *> VarList, SourceLocation EndLoc) @@ -716,7 +861,8 @@ public: class OpenACCPresentClause final : public OpenACCClauseWithVarList, - public llvm::TrailingObjects<OpenACCPresentClause, Expr *> { + private llvm::TrailingObjects<OpenACCPresentClause, Expr *> { + friend TrailingObjects; OpenACCPresentClause(SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef<Expr *> VarList, SourceLocation EndLoc) @@ -738,7 +884,8 @@ public: class OpenACCCopyClause final : public OpenACCClauseWithVarList, - public llvm::TrailingObjects<OpenACCCopyClause, Expr *> { + private llvm::TrailingObjects<OpenACCCopyClause, Expr *> { + friend TrailingObjects; OpenACCCopyClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef<Expr *> VarList, @@ -767,7 +914,8 @@ public: class OpenACCCopyInClause final : public OpenACCClauseWithVarList, - public llvm::TrailingObjects<OpenACCCopyInClause, Expr *> { + private llvm::TrailingObjects<OpenACCCopyInClause, Expr *> { + friend TrailingObjects; bool IsReadOnly; OpenACCCopyInClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc, @@ -799,7 +947,8 @@ public: class OpenACCCopyOutClause final : public OpenACCClauseWithVarList, - public llvm::TrailingObjects<OpenACCCopyOutClause, Expr *> { + private llvm::TrailingObjects<OpenACCCopyOutClause, Expr *> { + friend TrailingObjects; bool IsZero; OpenACCCopyOutClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc, @@ -831,7 +980,8 @@ public: class OpenACCCreateClause final : public OpenACCClauseWithVarList, - public llvm::TrailingObjects<OpenACCCreateClause, Expr *> { + private llvm::TrailingObjects<OpenACCCreateClause, Expr *> { + friend TrailingObjects; bool IsZero; OpenACCCreateClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc, @@ -863,7 +1013,8 @@ public: class OpenACCReductionClause final : public OpenACCClauseWithVarList, - public llvm::TrailingObjects<OpenACCReductionClause, Expr *> { + private llvm::TrailingObjects<OpenACCReductionClause, Expr *> { + friend TrailingObjects; OpenACCReductionOperator Op; OpenACCReductionClause(SourceLocation BeginLoc, SourceLocation LParenLoc, diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 76b598a5db23..f5b32ed51698 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2151,8 +2151,11 @@ DEF_TRAVERSE_DECL(DecompositionDecl, { }) DEF_TRAVERSE_DECL(BindingDecl, { - if (getDerived().shouldVisitImplicitCode()) + if (getDerived().shouldVisitImplicitCode()) { TRY_TO(TraverseStmt(D->getBinding())); + if (const auto HoldingVar = D->getHoldingVar()) + TRY_TO(TraverseDecl(HoldingVar)); + } }) DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); }) @@ -4058,6 +4061,25 @@ DEF_TRAVERSE_STMT(OpenACCLoopConstruct, { TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); }) DEF_TRAVERSE_STMT(OpenACCCombinedConstruct, { TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); }) +DEF_TRAVERSE_STMT(OpenACCDataConstruct, + { TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); }) +DEF_TRAVERSE_STMT(OpenACCEnterDataConstruct, + { TRY_TO(VisitOpenACCClauseList(S->clauses())); }) +DEF_TRAVERSE_STMT(OpenACCExitDataConstruct, + { TRY_TO(VisitOpenACCClauseList(S->clauses())); }) +DEF_TRAVERSE_STMT(OpenACCHostDataConstruct, + { TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); }) +DEF_TRAVERSE_STMT(OpenACCWaitConstruct, { + if (S->hasDevNumExpr()) + TRY_TO(TraverseStmt(S->getDevNumExpr())); + for (auto *E : S->getQueueIdExprs()) + TRY_TO(TraverseStmt(E)); + TRY_TO(VisitOpenACCClauseList(S->clauses())); +}) +DEF_TRAVERSE_STMT(OpenACCInitConstruct, + { TRY_TO(VisitOpenACCClauseList(S->clauses())); }) +DEF_TRAVERSE_STMT(OpenACCShutdownConstruct, + { TRY_TO(VisitOpenACCClauseList(S->clauses())); }) // Traverse HLSL: Out argument expression DEF_TRAVERSE_STMT(HLSLOutArgExpr, {}) diff --git a/clang/include/clang/AST/Redeclarable.h b/clang/include/clang/AST/Redeclarable.h index 8d320a9ced27..ee21f11e5f70 100644 --- a/clang/include/clang/AST/Redeclarable.h +++ b/clang/include/clang/AST/Redeclarable.h @@ -113,25 +113,24 @@ protected: DeclLink(PreviousTag, decl_type *D) : Link(NotKnownLatest(Previous(D))) {} bool isFirst() const { - return Link.is<KnownLatest>() || + return isa<KnownLatest>(Link) || // FIXME: 'template' is required on the next line due to an // apparent clang bug. - Link.get<NotKnownLatest>().template is<UninitializedLatest>(); + isa<UninitializedLatest>(cast<NotKnownLatest>(Link)); } decl_type *getPrevious(const decl_type *D) const { - if (Link.is<NotKnownLatest>()) { - NotKnownLatest NKL = Link.get<NotKnownLatest>(); - if (NKL.is<Previous>()) - return static_cast<decl_type*>(NKL.get<Previous>()); + if (NotKnownLatest NKL = dyn_cast<NotKnownLatest>(Link)) { + if (auto *Prev = dyn_cast<Previous>(NKL)) + return static_cast<decl_type *>(Prev); // Allocate the generational 'most recent' cache now, if needed. Link = KnownLatest(*reinterpret_cast<const ASTContext *>( - NKL.get<UninitializedLatest>()), + cast<UninitializedLatest>(NKL)), const_cast<decl_type *>(D)); } - return static_cast<decl_type*>(Link.get<KnownLatest>().get(D)); + return static_cast<decl_type *>(cast<KnownLatest>(Link).get(D)); } void setPrevious(decl_type *D) { @@ -141,25 +140,24 @@ protected: void setLatest(decl_type *D) { assert(isFirst() && "decl became canonical unexpectedly"); - if (Link.is<NotKnownLatest>()) { - NotKnownLatest NKL = Link.get<NotKnownLatest>(); + if (NotKnownLatest NKL = dyn_cast<NotKnownLatest>(Link)) { Link = KnownLatest(*reinterpret_cast<const ASTContext *>( - NKL.get<UninitializedLatest>()), + cast<UninitializedLatest>(NKL)), D); } else { - auto Latest = Link.get<KnownLatest>(); + auto Latest = cast<KnownLatest>(Link); Latest.set(D); Link = Latest; } } - void markIncomplete() { Link.get<KnownLatest>().markIncomplete(); } + void markIncomplete() { cast<KnownLatest>(Link).markIncomplete(); } Decl *getLatestNotUpdated() const { assert(isFirst() && "expected a canonical decl"); - if (Link.is<NotKnownLatest>()) + if (isa<NotKnownLatest>(Link)) return nullptr; - return Link.get<KnownLatest>().getNotUpdated(); + return cast<KnownLatest>(Link).getNotUpdated(); } }; diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 83fafbabb1d4..405c6166adb1 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -109,6 +109,8 @@ protected: //===--- Statement bitfields classes ---===// + #define NumStmtBits 9 + class StmtBitfields { friend class ASTStmtReader; friend class ASTStmtWriter; @@ -116,9 +118,8 @@ protected: /// The statement class. LLVM_PREFERRED_TYPE(StmtClass) - unsigned sClass : 8; + unsigned sClass : NumStmtBits; }; - enum { NumStmtBits = 8 }; class NullStmtBitfields { friend class ASTStmtReader; diff --git a/clang/include/clang/AST/StmtOpenACC.h b/clang/include/clang/AST/StmtOpenACC.h index fa8793e74082..e311eded5599 100644 --- a/clang/include/clang/AST/StmtOpenACC.h +++ b/clang/include/clang/AST/StmtOpenACC.h @@ -127,11 +127,12 @@ public: /// the 'Kind'. class OpenACCComputeConstruct final : public OpenACCAssociatedStmtConstruct, - public llvm::TrailingObjects<OpenACCComputeConstruct, - const OpenACCClause *> { + private llvm::TrailingObjects<OpenACCComputeConstruct, + const OpenACCClause *> { friend class ASTStmtWriter; friend class ASTStmtReader; friend class ASTContext; + friend TrailingObjects; OpenACCComputeConstruct(unsigned NumClauses) : OpenACCAssociatedStmtConstruct( OpenACCComputeConstructClass, OpenACCDirectiveKind::Invalid, @@ -189,7 +190,7 @@ public: /// Construct. class OpenACCLoopConstruct final : public OpenACCAssociatedStmtConstruct, - public llvm::TrailingObjects<OpenACCLoopConstruct, + private llvm::TrailingObjects<OpenACCLoopConstruct, const OpenACCClause *> { // The compute/combined construct kind this loop is associated with, or // invalid if this is an orphaned loop construct. @@ -202,6 +203,7 @@ class OpenACCLoopConstruct final friend class OpenACCAssociatedStmtConstruct; friend class OpenACCCombinedConstruct; friend class OpenACCComputeConstruct; + friend TrailingObjects; OpenACCLoopConstruct(unsigned NumClauses); @@ -245,8 +247,9 @@ public: // shared with both loop and compute constructs. class OpenACCCombinedConstruct final : public OpenACCAssociatedStmtConstruct, - public llvm::TrailingObjects<OpenACCCombinedConstruct, + private llvm::TrailingObjects<OpenACCCombinedConstruct, const OpenACCClause *> { + friend TrailingObjects; OpenACCCombinedConstruct(unsigned NumClauses) : OpenACCAssociatedStmtConstruct( OpenACCCombinedConstructClass, OpenACCDirectiveKind::Invalid, @@ -292,5 +295,382 @@ public: return const_cast<OpenACCCombinedConstruct *>(this)->getLoop(); } }; + +// This class represents a 'data' construct, which has an associated statement +// and clauses, but is otherwise pretty simple. +class OpenACCDataConstruct final + : public OpenACCAssociatedStmtConstruct, + private llvm::TrailingObjects<OpenACCDataConstruct, + const OpenACCClause *> { + friend TrailingObjects; + OpenACCDataConstruct(unsigned NumClauses) + : OpenACCAssociatedStmtConstruct( + OpenACCDataConstructClass, OpenACCDirectiveKind::Data, + SourceLocation{}, SourceLocation{}, SourceLocation{}, + /*AssociatedStmt=*/nullptr) { + std::uninitialized_value_construct( + getTrailingObjects<const OpenACCClause *>(), + getTrailingObjects<const OpenACCClause *>() + NumClauses); + setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), + NumClauses)); + } + + OpenACCDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, + ArrayRef<const OpenACCClause *> Clauses, + Stmt *StructuredBlock) + : OpenACCAssociatedStmtConstruct(OpenACCDataConstructClass, + OpenACCDirectiveKind::Data, Start, + DirectiveLoc, End, StructuredBlock) { + std::uninitialized_copy(Clauses.begin(), Clauses.end(), + getTrailingObjects<const OpenACCClause *>()); + setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), + Clauses.size())); + } + void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); } + +public: + static bool classof(const Stmt *T) { + return T->getStmtClass() == OpenACCDataConstructClass; + } + + static OpenACCDataConstruct *CreateEmpty(const ASTContext &C, + unsigned NumClauses); + static OpenACCDataConstruct *Create(const ASTContext &C, SourceLocation Start, + SourceLocation DirectiveLoc, + SourceLocation End, + ArrayRef<const OpenACCClause *> Clauses, + Stmt *StructuredBlock); + Stmt *getStructuredBlock() { return getAssociatedStmt(); } + const Stmt *getStructuredBlock() const { + return const_cast<OpenACCDataConstruct *>(this)->getStructuredBlock(); + } +}; +// This class represents a 'enter data' construct, which JUST has clauses. +class OpenACCEnterDataConstruct final + : public OpenACCConstructStmt, + private llvm::TrailingObjects<OpenACCEnterDataConstruct, + const OpenACCClause *> { + friend TrailingObjects; + OpenACCEnterDataConstruct(unsigned NumClauses) + : OpenACCConstructStmt(OpenACCEnterDataConstructClass, + OpenACCDirectiveKind::EnterData, SourceLocation{}, + SourceLocation{}, SourceLocation{}) { + std::uninitialized_value_construct( + getTrailingObjects<const OpenACCClause *>(), + getTrailingObjects<const OpenACCClause *>() + NumClauses); + setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), + NumClauses)); + } + OpenACCEnterDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, + ArrayRef<const OpenACCClause *> Clauses) + : OpenACCConstructStmt(OpenACCEnterDataConstructClass, + OpenACCDirectiveKind::EnterData, Start, + DirectiveLoc, End) { + std::uninitialized_copy(Clauses.begin(), Clauses.end(), + getTrailingObjects<const OpenACCClause *>()); + setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), + Clauses.size())); + } + +public: + static bool classof(const Stmt *T) { + return T->getStmtClass() == OpenACCEnterDataConstructClass; + } + static OpenACCEnterDataConstruct *CreateEmpty(const ASTContext &C, + unsigned NumClauses); + static OpenACCEnterDataConstruct * + Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, ArrayRef<const OpenACCClause *> Clauses); +}; +// This class represents a 'exit data' construct, which JUST has clauses. +class OpenACCExitDataConstruct final + : public OpenACCConstructStmt, + private llvm::TrailingObjects<OpenACCExitDataConstruct, + const OpenACCClause *> { + friend TrailingObjects; + OpenACCExitDataConstruct(unsigned NumClauses) + : OpenACCConstructStmt(OpenACCExitDataConstructClass, + OpenACCDirectiveKind::ExitData, SourceLocation{}, + SourceLocation{}, SourceLocation{}) { + std::uninitialized_value_construct( + getTrailingObjects<const OpenACCClause *>(), + getTrailingObjects<const OpenACCClause *>() + NumClauses); + setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), + NumClauses)); + } + OpenACCExitDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, + ArrayRef<const OpenACCClause *> Clauses) + : OpenACCConstructStmt(OpenACCExitDataConstructClass, + OpenACCDirectiveKind::ExitData, Start, + DirectiveLoc, End) { + std::uninitialized_copy(Clauses.begin(), Clauses.end(), + getTrailingObjects<const OpenACCClause *>()); + setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), + Clauses.size())); + } + +public: + static bool classof(const Stmt *T) { + return T->getStmtClass() == OpenACCExitDataConstructClass; + } + static OpenACCExitDataConstruct *CreateEmpty(const ASTContext &C, + unsigned NumClauses); + static OpenACCExitDataConstruct * + Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, ArrayRef<const OpenACCClause *> Clauses); +}; +// This class represents a 'host_data' construct, which has an associated +// statement and clauses, but is otherwise pretty simple. +class OpenACCHostDataConstruct final + : public OpenACCAssociatedStmtConstruct, + private llvm::TrailingObjects<OpenACCHostDataConstruct, + const OpenACCClause *> { + friend TrailingObjects; + OpenACCHostDataConstruct(unsigned NumClauses) + : OpenACCAssociatedStmtConstruct( + OpenACCHostDataConstructClass, OpenACCDirectiveKind::HostData, + SourceLocation{}, SourceLocation{}, SourceLocation{}, + /*AssociatedStmt=*/nullptr) { + std::uninitialized_value_construct( + getTrailingObjects<const OpenACCClause *>(), + getTrailingObjects<const OpenACCClause *>() + NumClauses); + setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), + NumClauses)); + } + OpenACCHostDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, + ArrayRef<const OpenACCClause *> Clauses, + Stmt *StructuredBlock) + : OpenACCAssociatedStmtConstruct(OpenACCHostDataConstructClass, + OpenACCDirectiveKind::HostData, Start, + DirectiveLoc, End, StructuredBlock) { + std::uninitialized_copy(Clauses.begin(), Clauses.end(), + getTrailingObjects<const OpenACCClause *>()); + setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), + Clauses.size())); + } + void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); } + +public: + static bool classof(const Stmt *T) { + return T->getStmtClass() == OpenACCHostDataConstructClass; + } + static OpenACCHostDataConstruct *CreateEmpty(const ASTContext &C, + unsigned NumClauses); + static OpenACCHostDataConstruct * + Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, ArrayRef<const OpenACCClause *> Clauses, + Stmt *StructuredBlock); + Stmt *getStructuredBlock() { return getAssociatedStmt(); } + const Stmt *getStructuredBlock() const { + return const_cast<OpenACCHostDataConstruct *>(this)->getStructuredBlock(); + } +}; + +// This class represents a 'wait' construct, which has some expressions plus a +// clause list. +class OpenACCWaitConstruct final + : public OpenACCConstructStmt, + private llvm::TrailingObjects<OpenACCWaitConstruct, Expr *, + OpenACCClause *> { + // FIXME: We should be storing a `const OpenACCClause *` to be consistent with + // the rest of the constructs, but TrailingObjects doesn't allow for mixing + // constness in its implementation of `getTrailingObjects`. + + friend TrailingObjects; + friend class ASTStmtWriter; + friend class ASTStmtReader; + // Locations of the left and right parens of the 'wait-argument' + // expression-list. + SourceLocation LParenLoc, RParenLoc; + // Location of the 'queues' keyword, if present. + SourceLocation QueuesLoc; + + // Number of the expressions being represented. Index '0' is always the + // 'devnum' expression, even if it not present. + unsigned NumExprs = 0; + + OpenACCWaitConstruct(unsigned NumExprs, unsigned NumClauses) + : OpenACCConstructStmt(OpenACCWaitConstructClass, + OpenACCDirectiveKind::Wait, SourceLocation{}, + SourceLocation{}, SourceLocation{}), + NumExprs(NumExprs) { + assert(NumExprs >= 1 && + "NumExprs should always be >= 1 because the 'devnum' " + "expr is represented by a null if necessary"); + std::uninitialized_value_construct(getExprPtr(), + getExprPtr() + NumExprs); + std::uninitialized_value_construct(getTrailingObjects<OpenACCClause *>(), + getTrailingObjects<OpenACCClause *>() + + NumClauses); + setClauseList(MutableArrayRef(const_cast<const OpenACCClause **>( + getTrailingObjects<OpenACCClause *>()), + NumClauses)); + } + + OpenACCWaitConstruct(SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation LParenLoc, Expr *DevNumExpr, + SourceLocation QueuesLoc, ArrayRef<Expr *> QueueIdExprs, + SourceLocation RParenLoc, SourceLocation End, + ArrayRef<const OpenACCClause *> Clauses) + : OpenACCConstructStmt(OpenACCWaitConstructClass, + OpenACCDirectiveKind::Wait, Start, DirectiveLoc, + End), + LParenLoc(LParenLoc), RParenLoc(RParenLoc), QueuesLoc(QueuesLoc), + NumExprs(QueueIdExprs.size() + 1) { + assert(NumExprs >= 1 && + "NumExprs should always be >= 1 because the 'devnum' " + "expr is represented by a null if necessary"); + + std::uninitialized_copy(&DevNumExpr, &DevNumExpr + 1, + getExprPtr()); + std::uninitialized_copy(QueueIdExprs.begin(), QueueIdExprs.end(), + getExprPtr() + 1); + + std::uninitialized_copy(const_cast<OpenACCClause **>(Clauses.begin()), + const_cast<OpenACCClause **>(Clauses.end()), + getTrailingObjects<OpenACCClause *>()); + setClauseList(MutableArrayRef(const_cast<const OpenACCClause **>( + getTrailingObjects<OpenACCClause *>()), + Clauses.size())); + } + + size_t numTrailingObjects(OverloadToken<Expr *>) const { return NumExprs; } + size_t numTrailingObjects(OverloadToken<const OpenACCClause *>) const { + return clauses().size(); + } + + Expr **getExprPtr() const { + return const_cast<Expr**>(getTrailingObjects<Expr *>()); + } + + llvm::ArrayRef<Expr *> getExprs() const { + return llvm::ArrayRef<Expr *>(getExprPtr(), NumExprs); + } + + llvm::ArrayRef<Expr *> getExprs() { + return llvm::ArrayRef<Expr *>(getExprPtr(), NumExprs); + } + +public: + static bool classof(const Stmt *T) { + return T->getStmtClass() == OpenACCWaitConstructClass; + } + + static OpenACCWaitConstruct * + CreateEmpty(const ASTContext &C, unsigned NumExprs, unsigned NumClauses); + + static OpenACCWaitConstruct * + Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc, + ArrayRef<Expr *> QueueIdExprs, SourceLocation RParenLoc, + SourceLocation End, ArrayRef<const OpenACCClause *> Clauses); + + SourceLocation getLParenLoc() const { return LParenLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + bool hasQueuesTag() const { return !QueuesLoc.isInvalid(); } + SourceLocation getQueuesLoc() const { return QueuesLoc; } + + bool hasDevNumExpr() const { return getExprs()[0]; } + Expr *getDevNumExpr() const { return getExprs()[0]; } + llvm::ArrayRef<Expr *> getQueueIdExprs() { return getExprs().drop_front(); } + llvm::ArrayRef<Expr *> getQueueIdExprs() const { + return getExprs().drop_front(); + } + + child_range children() { + Stmt **Begin = reinterpret_cast<Stmt **>(getExprPtr()); + return child_range(Begin, Begin + NumExprs); + } + + const_child_range children() const { + Stmt *const *Begin = + reinterpret_cast<Stmt *const *>(getExprPtr()); + return const_child_range(Begin, Begin + NumExprs); + } +}; + +// This class represents an 'init' construct, which has just a clause list. +class OpenACCInitConstruct final + : public OpenACCConstructStmt, + private llvm::TrailingObjects<OpenACCInitConstruct, + const OpenACCClause *> { + friend TrailingObjects; + OpenACCInitConstruct(unsigned NumClauses) + : OpenACCConstructStmt(OpenACCInitConstructClass, + OpenACCDirectiveKind::Init, SourceLocation{}, + SourceLocation{}, SourceLocation{}) { + std::uninitialized_value_construct( + getTrailingObjects<const OpenACCClause *>(), + getTrailingObjects<const OpenACCClause *>() + NumClauses); + setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), + NumClauses)); + } + OpenACCInitConstruct(SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, + ArrayRef<const OpenACCClause *> Clauses) + : OpenACCConstructStmt(OpenACCInitConstructClass, + OpenACCDirectiveKind::Init, Start, DirectiveLoc, + End) { + std::uninitialized_copy(Clauses.begin(), Clauses.end(), + getTrailingObjects<const OpenACCClause *>()); + setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), + Clauses.size())); + } + +public: + static bool classof(const Stmt *T) { + return T->getStmtClass() == OpenACCInitConstructClass; + } + static OpenACCInitConstruct *CreateEmpty(const ASTContext &C, + unsigned NumClauses); + static OpenACCInitConstruct *Create(const ASTContext &C, SourceLocation Start, + SourceLocation DirectiveLoc, + SourceLocation End, + ArrayRef<const OpenACCClause *> Clauses); +}; + +// This class represents a 'shutdown' construct, which has just a clause list. +class OpenACCShutdownConstruct final + : public OpenACCConstructStmt, + private llvm::TrailingObjects<OpenACCShutdownConstruct, + const OpenACCClause *> { + friend TrailingObjects; + OpenACCShutdownConstruct(unsigned NumClauses) + : OpenACCConstructStmt(OpenACCShutdownConstructClass, + OpenACCDirectiveKind::Shutdown, SourceLocation{}, + SourceLocation{}, SourceLocation{}) { + std::uninitialized_value_construct( + getTrailingObjects<const OpenACCClause *>(), + getTrailingObjects<const OpenACCClause *>() + NumClauses); + setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), + NumClauses)); + } + OpenACCShutdownConstruct(SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, + ArrayRef<const OpenACCClause *> Clauses) + : OpenACCConstructStmt(OpenACCShutdownConstructClass, + OpenACCDirectiveKind::Shutdown, Start, + DirectiveLoc, End) { + std::uninitialized_copy(Clauses.begin(), Clauses.end(), + getTrailingObjects<const OpenACCClause *>()); + setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), + Clauses.size())); + } + +public: + static bool classof(const Stmt *T) { + return T->getStmtClass() == OpenACCShutdownConstructClass; + } + static OpenACCShutdownConstruct *CreateEmpty(const ASTContext &C, + unsigned NumClauses); + static OpenACCShutdownConstruct * + Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, ArrayRef<const OpenACCClause *> Clauses); +}; + } // namespace clang #endif // LLVM_CLANG_AST_STMTOPENACC_H diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h index a8f0263d5505..9d0ee24a4f5e 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -484,7 +484,7 @@ private: Pointer; TemplateTemplateArgLocInfo *getTemplate() const { - return Pointer.get<TemplateTemplateArgLocInfo *>(); + return cast<TemplateTemplateArgLocInfo *>(Pointer); } public: @@ -499,10 +499,10 @@ public: SourceLocation EllipsisLoc); TypeSourceInfo *getAsTypeSourceInfo() const { - return Pointer.get<TypeSourceInfo *>(); + return cast<TypeSourceInfo *>(Pointer); } - Expr *getAsExpr() const { return Pointer.get<Expr *>(); } + Expr *getAsExpr() const { return cast<Expr *>(Pointer); } NestedNameSpecifierLoc getTemplateQualifierLoc() const { const auto *Template = getTemplate(); diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index 988b142a7672..5383b53fdc49 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -411,6 +411,13 @@ public: void VisitOpenACCConstructStmt(const OpenACCConstructStmt *S); void VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *S); void VisitOpenACCCombinedConstruct(const OpenACCCombinedConstruct *S); + void VisitOpenACCDataConstruct(const OpenACCDataConstruct *S); + void VisitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct *S); + void VisitOpenACCExitDataConstruct(const OpenACCExitDataConstruct *S); + void VisitOpenACCHostDataConstruct(const OpenACCHostDataConstruct *S); + void VisitOpenACCWaitConstruct(const OpenACCWaitConstruct *S); + void VisitOpenACCInitConstruct(const OpenACCInitConstruct *S); + void VisitOpenACCShutdownConstruct(const OpenACCShutdownConstruct *S); void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *S); void VisitEmbedExpr(const EmbedExpr *S); void VisitAtomicExpr(const AtomicExpr *AE); diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 6fd6c73a516f..09c98f642852 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -934,11 +934,11 @@ class QualType { Qualifiers::FastWidth> Value; const ExtQuals *getExtQualsUnsafe() const { - return Value.getPointer().get<const ExtQuals*>(); + return cast<const ExtQuals *>(Value.getPointer()); } const Type *getTypePtrUnsafe() const { - return Value.getPointer().get<const Type*>(); + return cast<const Type *>(Value.getPointer()); } const ExtQualsTypeCommonBase *getCommonPtr() const { @@ -1064,7 +1064,7 @@ public: /// "non-fast" qualifiers, e.g., those that are stored in an ExtQualType /// instance. bool hasLocalNonFastQualifiers() const { - return Value.getPointer().is<const ExtQuals*>(); + return isa<const ExtQuals *>(Value.getPointer()); } /// Retrieve the set of qualifiers local to this particular QualType @@ -6553,7 +6553,7 @@ public: /// Represents a C++11 auto or C++14 decltype(auto) type, possibly constrained /// by a type-constraint. -class AutoType : public DeducedType, public llvm::FoldingSetNode { +class AutoType : public DeducedType { friend class ASTContext; // ASTContext creates these ConceptDecl *TypeConstraintConcept; diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 897aa25dc95c..9a046714068a 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -2125,6 +2125,16 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr; extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr; +/// Matches expressions that refer to dependent scope declarations. +/// +/// example matches T::v; +/// \code +/// template <class T> class X : T { void f() { T::v; } }; +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher<Stmt, + DependentScopeDeclRefExpr> + dependentScopeDeclRefExpr; + /// Matches a reference to an ObjCIvar. /// /// Example: matches "a" in "init" method: @@ -7701,6 +7711,16 @@ AST_MATCHER_P(DecayedType, hasDecayedType, internal::Matcher<QualType>, return InnerType.matches(Node.getDecayedType(), Finder, Builder); } +/// Matches a dependent name type +/// +/// Example matches T::type +/// \code +/// template <typename T> struct declToImport { +/// typedef typename T::type dependent_name; +/// }; +/// \endcode +extern const AstTypeMatcher<DependentNameType> dependentNameType; + /// Matches declarations whose declaration context, interpreted as a /// Decl, matches \c InnerMatcher. /// diff --git a/clang/include/clang/Analysis/Analyses/ThreadSafety.h b/clang/include/clang/Analysis/Analyses/ThreadSafety.h index 0866b09bab29..0fcf5bed1285 100644 --- a/clang/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/clang/include/clang/Analysis/Analyses/ThreadSafety.h @@ -223,6 +223,42 @@ public: virtual void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName, SourceLocation Loc) {} + /// Warn when an actual underlying mutex of a scoped lockable does not match + /// the expected. + /// \param Loc -- The location of the call expression. + /// \param DLoc -- The location of the function declaration. + /// \param ScopeName -- The name of the scope passed to the function. + /// \param Kind -- The kind of the expected mutex. + /// \param Expected -- The name of the expected mutex. + /// \param Actual -- The name of the actual mutex. + virtual void handleUnmatchedUnderlyingMutexes(SourceLocation Loc, + SourceLocation DLoc, + Name ScopeName, StringRef Kind, + Name Expected, Name Actual) {} + + /// Warn when we get fewer underlying mutexes than expected. + /// \param Loc -- The location of the call expression. + /// \param DLoc -- The location of the function declaration. + /// \param ScopeName -- The name of the scope passed to the function. + /// \param Kind -- The kind of the expected mutex. + /// \param Expected -- The name of the expected mutex. + virtual void handleExpectMoreUnderlyingMutexes(SourceLocation Loc, + SourceLocation DLoc, + Name ScopeName, StringRef Kind, + Name Expected) {} + + /// Warn when we get more underlying mutexes than expected. + /// \param Loc -- The location of the call expression. + /// \param DLoc -- The location of the function declaration. + /// \param ScopeName -- The name of the scope passed to the function. + /// \param Kind -- The kind of the actual mutex. + /// \param Actual -- The name of the actual mutex. + virtual void handleExpectFewerUnderlyingMutexes(SourceLocation Loc, + SourceLocation DLoc, + Name ScopeName, + StringRef Kind, Name Actual) { + } + /// Warn that L1 cannot be acquired before L2. virtual void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name, SourceLocation Loc) {} diff --git a/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h b/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h new file mode 100644 index 000000000000..3e4016518eaa --- /dev/null +++ b/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h @@ -0,0 +1,63 @@ +//===-- SmartPointerAccessorCaching.h ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines utilities to help cache accessors for smart pointer +// like objects. +// +// These should be combined with CachedConstAccessorsLattice. +// Beyond basic const accessors, smart pointers may have the following two +// additional issues: +// +// 1) There may be multiple accessors for the same underlying object, e.g. +// `operator->`, `operator*`, and `get`. Users may use a mixture of these +// accessors, so the cache should unify them. +// +// 2) There may be non-const overloads of accessors. They are still safe to +// cache, as they don't modify the container object. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SMARTPOINTERACCESSORCACHING_H +#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SMARTPOINTERACCESSORCACHING_H + +#include <cassert> + +#include "clang/AST/Decl.h" +#include "clang/AST/Stmt.h" +#include "clang/ASTMatchers/ASTMatchers.h" + +namespace clang::dataflow { + +/// Matchers: +/// For now, these match on any class with an `operator*` or `operator->` +/// where the return types have a similar shape as std::unique_ptr +/// and std::optional. +/// +/// - `*` returns a reference to a type `T` +/// - `->` returns a pointer to `T` +/// - `get` returns a pointer to `T` +/// - `value` returns a reference `T` +/// +/// (1) The `T` should all match across the accessors (ignoring qualifiers). +/// +/// (2) The specific accessor used in a call isn't required to be const, +/// but the class must have a const overload of each accessor. +/// +/// For now, we don't have customization to ignore certain classes. +/// For example, if writing a ClangTidy check for `std::optional`, these +/// would also match `std::optional`. In order to have special handling +/// for `std::optional`, we assume the (Matcher, TransferFunction) case +/// with custom handling is ordered early so that these generic cases +/// do not trigger. +ast_matchers::StatementMatcher isSmartPointerLikeOperatorStar(); +ast_matchers::StatementMatcher isSmartPointerLikeOperatorArrow(); +ast_matchers::StatementMatcher isSmartPointerLikeValueMethodCall(); +ast_matchers::StatementMatcher isSmartPointerLikeGetMethodCall(); + +} // namespace clang::dataflow + +#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SMARTPOINTERACCESSORCACHING_H diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 17fc36fbe2ac..52ad72eb608c 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3763,7 +3763,7 @@ def AcquireCapability : InheritableAttr { Clang<"acquire_shared_capability", 0>, GNU<"exclusive_lock_function">, GNU<"shared_lock_function">]; - let Subjects = SubjectList<[Function]>; + let Subjects = SubjectList<[Function, ParmVar]>; let LateParsed = LateAttrParseStandard; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; @@ -3795,7 +3795,7 @@ def ReleaseCapability : InheritableAttr { Clang<"release_shared_capability", 0>, Clang<"release_generic_capability", 0>, Clang<"unlock_function", 0>]; - let Subjects = SubjectList<[Function]>; + let Subjects = SubjectList<[Function, ParmVar]>; let LateParsed = LateAttrParseStandard; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; @@ -3819,7 +3819,7 @@ def RequiresCapability : InheritableAttr { let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; let InheritEvenIfAlreadyPresent = 1; - let Subjects = SubjectList<[Function]>; + let Subjects = SubjectList<[Function, ParmVar]>; let Accessors = [Accessor<"isShared", [Clang<"requires_shared_capability", 0>, Clang<"shared_locks_required", 0>]>]; let Documentation = [Undocumented]; @@ -3941,7 +3941,7 @@ def LocksExcluded : InheritableAttr { let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; let InheritEvenIfAlreadyPresent = 1; - let Subjects = SubjectList<[Function]>; + let Subjects = SubjectList<[Function, ParmVar]>; let Documentation = [Undocumented]; } @@ -4651,6 +4651,13 @@ def HLSLNumThreads: InheritableAttr { let Documentation = [NumThreadsDocs]; } +def HLSLSV_GroupThreadID: HLSLAnnotationAttr { + let Spellings = [HLSLAnnotation<"SV_GroupThreadID">]; + let Subjects = SubjectList<[ParmVar, Field]>; + let LangOpts = [HLSL]; + let Documentation = [HLSLSV_GroupThreadIDDocs]; +} + def HLSLSV_GroupID: HLSLAnnotationAttr { let Spellings = [HLSLAnnotation<"SV_GroupID">]; let Subjects = SubjectList<[ParmVar, Field]>; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 7a82b8fa3205..fdad4c9a3ea1 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -7941,6 +7941,17 @@ randomized. }]; } +def HLSLSV_GroupThreadIDDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``SV_GroupThreadID`` semantic, when applied to an input parameter, specifies which +individual thread within a thread group is executing in. This attribute is +only supported in compute shaders. + +The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-groupthreadid + }]; +} + def HLSLSV_GroupIDDocs : Documentation { let Category = DocCatFunction; let Content = [{ diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h index 89f65682ae5b..e27d8ccce736 100644 --- a/clang/include/clang/Basic/Builtins.h +++ b/clang/include/clang/Basic/Builtins.h @@ -103,9 +103,7 @@ public: llvm::StringRef getName(unsigned ID) const { return getRecord(ID).Name; } /// Get the type descriptor string for the specified builtin. - const char *getTypeString(unsigned ID) const { - return getRecord(ID).Type; - } + const char *getTypeString(unsigned ID) const { return getRecord(ID).Type; } /// Return true if this function is a target-specific builtin. bool isTSBuiltin(unsigned ID) const { diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index e2c3d3c53557..b5b47ae27460 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -1450,25 +1450,25 @@ def ElementwiseFma : Builtin { def ElementwiseAddSat : Builtin { let Spellings = ["__builtin_elementwise_add_sat"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr]; let Prototype = "void(...)"; } def ElementwiseSubSat : Builtin { let Spellings = ["__builtin_elementwise_sub_sat"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr]; let Prototype = "void(...)"; } def ReduceMax : Builtin { let Spellings = ["__builtin_reduce_max"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr]; let Prototype = "void(...)"; } def ReduceMin : Builtin { let Spellings = ["__builtin_reduce_min"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr]; let Prototype = "void(...)"; } @@ -4762,6 +4762,12 @@ def HLSLAsDouble : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLWaveActiveAllTrue : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_wave_active_all_true"]; + let Attributes = [NoThrow, Const]; + let Prototype = "bool(bool)"; +} + def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_wave_active_any_true"]; let Attributes = [NoThrow, Const]; diff --git a/clang/include/clang/Basic/BuiltinsHexagon.def b/clang/include/clang/Basic/BuiltinsHexagon.def index 0dc0f4567dd4..adff9f884c04 100644 --- a/clang/include/clang/Basic/BuiltinsHexagon.def +++ b/clang/include/clang/Basic/BuiltinsHexagon.def @@ -17,8 +17,12 @@ # define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS) #endif +#pragma push_macro("V79") +#define V79 "v79" +#pragma push_macro("V75") +#define V75 "v75|" V79 #pragma push_macro("V73") -#define V73 "v73" +#define V73 "v73|" V75 #pragma push_macro("V71") #define V71 "v71|" V73 #pragma push_macro("V69") @@ -40,8 +44,12 @@ #pragma push_macro("V5") #define V5 "v5|" V55 +#pragma push_macro("HVXV79") +#define HVXV79 "hvxv79" +#pragma push_macro("HVXV75") +#define HVXV75 "hvxv75|" HVXV79 #pragma push_macro("HVXV73") -#define HVXV73 "hvxv73" +#define HVXV73 "hvxv73|" HVXV75 #pragma push_macro("HVXV71") #define HVXV71 "hvxv71|" HVXV73 #pragma push_macro("HVXV69") @@ -143,6 +151,8 @@ TARGET_BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B,"V64iV64iV32iLLi","", " #pragma pop_macro("HVXV69") #pragma pop_macro("HVXV71") #pragma pop_macro("HVXV73") +#pragma pop_macro("HVXV75") +#pragma pop_macro("HVXV79") #pragma pop_macro("V5") #pragma pop_macro("V55") @@ -155,6 +165,8 @@ TARGET_BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B,"V64iV64iV32iLLi","", " #pragma pop_macro("V69") #pragma pop_macro("V71") #pragma pop_macro("V73") +#pragma pop_macro("V75") +#pragma pop_macro("V79") #undef BUILTIN #undef TARGET_BUILTIN diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 2dcf98b46566..c555fb3b72d6 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -186,7 +186,7 @@ public: std::string ProfileExcludeFiles; /// The version string to put into coverage files. - char CoverageVersion[4]; + char CoverageVersion[4] = {'0', '0', '0', '0'}; /// Enable additional debugging information. std::string DebugPass; @@ -380,6 +380,10 @@ public: /// Set of sanitizer checks that trap rather than diagnose. SanitizerSet SanitizeTrap; + /// Set of sanitizer checks that can merge handlers (smaller code size at + /// the expense of debuggability). + SanitizerSet SanitizeMergeHandlers; + /// List of backend command-line options for -fembed-bitcode. std::vector<uint8_t> CmdArgs; diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h index d271accca3d3..510b782e35d0 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -560,7 +560,8 @@ private: ArgToStringFnTy ArgToStringFn; /// Whether the diagnostic should be suppressed in FilePath. - llvm::unique_function<bool(diag::kind, StringRef /*FilePath*/) const> + llvm::unique_function<bool(diag::kind, SourceLocation /*DiagLoc*/, + const SourceManager &) const> DiagSuppressionMapping; public: @@ -972,7 +973,7 @@ public: /// These take presumed locations into account, and can still be overriden by /// clang-diagnostics pragmas. void setDiagSuppressionMapping(llvm::MemoryBuffer &Input); - bool isSuppressedViaMapping(diag::kind DiagId, StringRef FilePath) const; + bool isSuppressedViaMapping(diag::kind DiagId, SourceLocation DiagLoc) const; /// Issue the message to the client. /// diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 5155b23d151c..42c39ac6606c 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -67,7 +67,7 @@ def err_drv_no_cuda_libdevice : Error< "libdevice">; def err_drv_no_rocm_device_lib : Error< - "cannot find ROCm device library%select{| for %1|for ABI version %1}0; provide its path via " + "cannot find ROCm device library%select{| for %1| for ABI version %1}0; provide its path via " "'--rocm-path' or '--rocm-device-lib-path', or pass '-nogpulib' to build " "without ROCm device library">; def err_drv_no_hip_runtime : Error< diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 9fa8d5901bd0..86fcae209c40 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -721,6 +721,9 @@ def warn_empty_init_statement : Warning< "has no effect">, InGroup<EmptyInitStatement>, DefaultIgnore; def err_keyword_as_parameter : Error < "invalid parameter name: '%0' is a keyword">; +def warn_pre_cxx26_ambiguous_pack_indexing_type : Warning< + "%0 is no longer a pack expansion but a pack " + "indexing type; add a name to specify a pack expansion">, InGroup<CXXPre26Compat>; // C++ derived classes def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 2137cb713164..330ae045616a 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3233,8 +3233,8 @@ def err_attribute_too_few_arguments : Error< "%0 attribute takes at least %1 argument%s1">; def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">; def err_attribute_invalid_bitint_vector_type : Error< - "'_BitInt' vector element width must be %select{a power of 2|" - "at least as wide as 'CHAR_BIT'}0">; + "'_BitInt' %select{vector|matrix}0 element width must be %select{a power of 2|" + "at least as wide as 'CHAR_BIT'}1">; def err_attribute_invalid_matrix_type : Error<"invalid matrix element type %0">; def err_attribute_bad_neon_vector_size : Error< "Neon vector size must be 64 or 128 bits">; @@ -3423,7 +3423,7 @@ def warn_typecheck_vector_element_sizes_not_equal : Warning< def err_ext_vector_component_exceeds_length : Error< "vector component access exceeds type %0">; def err_ext_vector_component_name_illegal : Error< - "illegal vector component name '%0'">; + "illegal vector component name %0">; def err_attribute_address_space_negative : Error< "address space is negative">; def err_attribute_address_space_too_high : Error< @@ -3999,6 +3999,10 @@ def warn_thread_attribute_decl_not_lockable : Warning< def warn_thread_attribute_decl_not_pointer : Warning< "%0 only applies to pointer types; type here is %1">, InGroup<ThreadSafetyAttributes>, DefaultIgnore; +def warn_thread_attribute_not_on_scoped_lockable_param : Warning< + "%0 attribute applies to function parameters only if their type is a " + "reference to a 'scoped_lockable'-annotated type">, + InGroup<ThreadSafetyAttributes>, DefaultIgnore; def err_attribute_argument_out_of_bounds_extra_info : Error< "%0 attribute parameter %1 is out of bounds: " "%plural{0:no parameters to index into|" @@ -4054,6 +4058,17 @@ def warn_acquired_before : Warning< def warn_acquired_before_after_cycle : Warning< "cycle in acquired_before/after dependencies, starting with '%0'">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; +def warn_unmatched_underlying_mutexes : Warning< + "%0 managed by '%1' is '%3' instead of '%2'">, + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; +def warn_expect_more_underlying_mutexes : Warning< + "%0 '%2' not managed by '%1'">, + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; +def warn_expect_fewer_underlying_mutexes : Warning< + "did not expect %0 '%2' to be managed by '%1'">, + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; +def note_managed_mismatch_here_for_param : Note< + "see attribute on parameter here">; // Thread safety warnings negative capabilities @@ -5863,10 +5878,10 @@ def err_pack_expansion_without_parameter_packs : Error< "pack expansion does not contain any unexpanded parameter packs">; def err_pack_expansion_length_conflict : Error< "pack expansion contains parameter packs %0 and %1 that have different " - "lengths (%2 vs. %3)">; + "lengths (%2 vs. %select{|at least }3%4))">; def err_pack_expansion_length_conflict_multilevel : Error< "pack expansion contains parameter pack %0 that has a different " - "length (%1 vs. %2) from outer parameter packs">; + "length (%1 vs. %select{|at least }2%3) from outer parameter packs">; def err_pack_expansion_length_conflict_partial : Error< "pack expansion contains parameter pack %0 that has a different " "length (at least %1 vs. %2) from outer parameter packs">; @@ -10237,16 +10252,16 @@ def warn_dangling_pointer_assignment : Warning< InGroup<DanglingAssignment>; def warn_dangling_reference_captured : Warning< "object whose reference is captured by '%0' will be destroyed at the end of " - "the full-expression">, InGroup<DanglingCapture>, DefaultIgnore; + "the full-expression">, InGroup<DanglingCapture>; def warn_dangling_reference_captured_by_unknown : Warning< "object whose reference is captured will be destroyed at the end of " - "the full-expression">, InGroup<DanglingCapture>, DefaultIgnore; + "the full-expression">, InGroup<DanglingCapture>; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. // Array comparisons have similar warnings def warn_comparison_always : Warning< - "%select{self-|array }0comparison always evaluates to " + "%select{self-|array |pointer }0comparison always evaluates to " "%select{a constant|true|false|'std::strong_ordering::equal'}1">, InGroup<TautologicalCompare>; def warn_comparison_bitwise_always : Warning< @@ -10274,6 +10289,11 @@ def warn_array_comparison : Warning< "to compare array addresses, use unary '+' to decay operands to pointers">, InGroup<DiagGroup<"array-compare">>; +def warn_array_comparison_cxx26 : Warning< + "comparison between two arrays is ill-formed in C++26; " + "to compare array addresses, use unary '+' to decay operands to pointers">, + InGroup<DiagGroup<"array-compare-cxx26">>, DefaultError; + def warn_stringcompare : Warning< "result of comparison against %select{a string literal|@encode}0 is " "unspecified (use an explicit string comparison function instead)">, @@ -12319,6 +12339,8 @@ def warn_noderef_to_dereferenceable_pointer : Warning< def err_builtin_launder_invalid_arg : Error< "%select{non-pointer|function pointer|void pointer}0 argument to " "'__builtin_launder' is not allowed">; +def err_builtin_assume_aligned_invalid_arg : Error< + "non-pointer argument to '__builtin_assume_aligned' is not allowed">; def err_builtin_is_within_lifetime_invalid_arg : Error< "%select{non-|function }0pointer argument to '__builtin_is_within_lifetime' " @@ -12662,8 +12684,8 @@ def err_acc_int_expr_requires_integer def err_acc_int_expr_incomplete_class_type : Error<"OpenACC integer expression has incomplete class type %0">; def err_acc_int_expr_explicit_conversion - : Error<"OpenACC integer expression type %0 requires explicit conversion " - "to %1">; + : Error<"OpenACC integer expression requires explicit conversion " + "from %0 to %1">; def note_acc_int_expr_conversion : Note<"conversion to %select{integral|enumeration}0 type %1">; def err_acc_int_expr_multiple_conversions @@ -12677,6 +12699,9 @@ def err_acc_not_a_var_ref : Error<"OpenACC variable is not a valid variable name, sub-array, array " "element,%select{| member of a composite variable,}0 or composite " "variable member">; +def err_acc_not_a_var_ref_use_device + : Error<"OpenACC variable in 'use_device' clause is not a valid variable " + "name or array name">; def err_acc_typecheck_subarray_value : Error<"OpenACC sub-array subscripted value is not an array or pointer">; def err_acc_subarray_function_type @@ -12711,9 +12736,9 @@ def err_acc_clause_cannot_combine : Error<"OpenACC clause '%0' may not appear on the same construct as a " "'%1' clause on a '%2' construct">; def err_acc_reduction_num_gangs_conflict - : Error< - "OpenACC 'reduction' clause may not appear on a 'parallel' construct " - "with a 'num_gangs' clause with more than 1 argument, have %0">; + : Error<"OpenACC '%1' clause %select{|with more than 1 argument }0may not " + "appear on a '%2' construct " + "with a '%3' clause%select{ with more than 1 argument|}0">; def err_acc_reduction_type : Error<"OpenACC 'reduction' variable must be of scalar type, sub-array, or a " "composite of scalar types;%select{| sub-array base}1 type is %0">; @@ -12755,31 +12780,33 @@ def err_acc_gang_multiple_elt : Error<"OpenACC 'gang' clause may have at most one %select{unnamed or " "'num'|'dim'|'static'}0 argument">; def err_acc_int_arg_invalid - : Error<"'%1' argument on '%0' clause is not permitted on a%select{n " - "orphaned|||}2 'loop' construct %select{|associated with a " - "'parallel' compute construct|associated with a 'kernels' compute " - "construct|associated with a 'serial' compute construct}2">; + : Error<"'%0' argument on '%1' clause is not permitted on a%select{|n " + "orphaned}2 '%3' construct%select{| associated with a '%5' compute " + "construct}4">; def err_acc_gang_dim_value : Error<"argument to 'gang' clause dimension must be %select{a constant " "expression|1, 2, or 3: evaluated to %1}0">; def err_acc_num_arg_conflict - : Error<"'num' argument to '%0' clause not allowed on a 'loop' construct " - "associated with a 'kernels' construct that has a " - "'%select{num_gangs|num_workers|vector_length}1' " - "clause">; + : Error<"'%0' argument to '%1' clause not allowed on a '%2' " + "construct%select{| associated with a '%4' construct}3 that has a " + "'%5' clause">; +def err_acc_num_arg_conflict_reverse + : Error<"'%0' clause not allowed on a 'kernels loop' construct that " + "has a '%1' clause with a%select{n| 'num'}2 argument">; def err_acc_clause_in_clause_region : Error<"loop with a '%0' clause may not exist in the region of a '%1' " - "clause%select{| on a 'kernels' compute construct}2">; + "clause%select{| on a '%3' construct}2">; def err_acc_gang_reduction_conflict : Error<"%select{OpenACC 'gang' clause with a 'dim' value greater than " "1|OpenACC 'reduction' clause}0 cannot " - "appear on the same 'loop' construct as a %select{'reduction' " + "appear on the same '%1' construct as a %select{'reduction' " "clause|'gang' clause with a 'dim' value greater than 1}0">; def err_acc_gang_reduction_numgangs_conflict - : Error<"OpenACC '%0' clause cannot appear on the same 'loop' construct " - "as a '%1' clause inside a compute construct with a " + : Error<"OpenACC '%0' clause cannot appear on the same '%2' construct as a " + "'%1' clause %select{inside a compute construct with a|and a}3 " "'num_gangs' clause with more than one argument">; -def err_reduction_op_mismatch + + def err_reduction_op_mismatch : Error<"OpenACC 'reduction' variable must have the same operator in all " "nested constructs (%0 vs %1)">; def err_acc_loop_variable_type @@ -12794,6 +12821,8 @@ def err_acc_loop_terminating_condition def err_acc_loop_not_monotonic : Error<"OpenACC '%0' variable must monotonically increase or decrease " "('++', '--', or compound assignment)">; +def err_acc_construct_one_clause_of + : Error<"OpenACC '%0' construct must have at least one %1 clause">; // AMDGCN builtins diagnostics def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">; diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index 15c59c6bcdf2..c82b6d9b5f6c 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -102,6 +102,7 @@ FEATURE(numerical_stability_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Nume FEATURE(memory_sanitizer, LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory)) +FEATURE(type_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Type)) FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread)) FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow)) FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) diff --git a/clang/include/clang/Basic/FileEntry.h b/clang/include/clang/Basic/FileEntry.h index 68d4bf609300..da5ba9097429 100644 --- a/clang/include/clang/Basic/FileEntry.h +++ b/clang/include/clang/Basic/FileEntry.h @@ -68,8 +68,13 @@ public: StringRef getNameAsRequested() const { return ME->first(); } const FileEntry &getFileEntry() const { - return *getBaseMapEntry().second->V.get<FileEntry *>(); + return *cast<FileEntry *>(getBaseMapEntry().second->V); } + + // This function is used if the buffer size needs to be increased + // due to potential z/OS EBCDIC -> UTF-8 conversion + inline void updateFileEntryBufferSize(unsigned BufferSize); + DirectoryEntryRef getDir() const { return ME->second->Dir; } inline off_t getSize() const; @@ -323,6 +328,8 @@ public: StringRef tryGetRealPathName() const { return RealPathName; } off_t getSize() const { return Size; } + // Size may increase due to potential z/OS EBCDIC -> UTF-8 conversion. + void setSize(off_t NewSize) { Size = NewSize; } unsigned getUID() const { return UID; } const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; } time_t getModificationTime() const { return ModTime; } @@ -353,6 +360,10 @@ bool FileEntryRef::isNamedPipe() const { return getFileEntry().isNamedPipe(); } void FileEntryRef::closeFile() const { getFileEntry().closeFile(); } +void FileEntryRef::updateFileEntryBufferSize(unsigned BufferSize) { + cast<FileEntry *>(getBaseMapEntry().second->V)->setSize(BufferSize); +} + } // end namespace clang #endif // LLVM_CLANG_BASIC_FILEENTRY_H diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h index ae9ebd9f5915..33d1cdb46f10 100644 --- a/clang/include/clang/Basic/IdentifierTable.h +++ b/clang/include/clang/Basic/IdentifierTable.h @@ -1012,7 +1012,7 @@ class Selector { } MultiKeywordSelector *getMultiKeywordSelector() const { - return InfoPtr.getPointer().get<MultiKeywordSelector *>(); + return cast<MultiKeywordSelector *>(InfoPtr.getPointer()); } unsigned getIdentifierInfoFlag() const { @@ -1020,7 +1020,7 @@ class Selector { // IMPORTANT NOTE: We have to reconstitute this data rather than use the // value directly from the PointerIntPair. See the comments in `InfoPtr` // for more details. - if (InfoPtr.getPointer().is<MultiKeywordSelector *>()) + if (isa<MultiKeywordSelector *>(InfoPtr.getPointer())) new_flags |= MultiArg; return new_flags; } diff --git a/clang/include/clang/Basic/OpenACCClauses.def b/clang/include/clang/Basic/OpenACCClauses.def index c65ebed751cf..1b619bc0dfd4 100644 --- a/clang/include/clang/Basic/OpenACCClauses.def +++ b/clang/include/clang/Basic/OpenACCClauses.def @@ -38,12 +38,17 @@ VISIT_CLAUSE(Create) CLAUSE_ALIAS(PCreate, Create, true) CLAUSE_ALIAS(PresentOrCreate, Create, true) VISIT_CLAUSE(Default) +VISIT_CLAUSE(Delete) +VISIT_CLAUSE(Detach) +VISIT_CLAUSE(DeviceNum) VISIT_CLAUSE(DevicePtr) VISIT_CLAUSE(DeviceType) CLAUSE_ALIAS(DType, DeviceType, false) +VISIT_CLAUSE(Finalize) VISIT_CLAUSE(FirstPrivate) VISIT_CLAUSE(Gang) VISIT_CLAUSE(If) +VISIT_CLAUSE(IfPresent) VISIT_CLAUSE(Independent) VISIT_CLAUSE(NoCreate) VISIT_CLAUSE(NumGangs) @@ -54,6 +59,7 @@ VISIT_CLAUSE(Reduction) VISIT_CLAUSE(Self) VISIT_CLAUSE(Seq) VISIT_CLAUSE(Tile) +VISIT_CLAUSE(UseDevice) VISIT_CLAUSE(Vector) VISIT_CLAUSE(VectorLength) VISIT_CLAUSE(Wait) diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h index ea0bf23468cb..7fb76271826a 100644 --- a/clang/include/clang/Basic/OpenACCKinds.h +++ b/clang/include/clang/Basic/OpenACCKinds.h @@ -158,6 +158,14 @@ inline bool isOpenACCCombinedDirectiveKind(OpenACCDirectiveKind K) { K == OpenACCDirectiveKind::KernelsLoop; } +// Tests 'K' to see if it is 'data', 'host_data', 'enter data', or 'exit data'. +inline bool isOpenACCDataDirectiveKind(OpenACCDirectiveKind K) { + return K == OpenACCDirectiveKind::Data || + K == OpenACCDirectiveKind::EnterData || + K == OpenACCDirectiveKind::ExitData || + K == OpenACCDirectiveKind::HostData; +} + enum class OpenACCAtomicKind : uint8_t { Read, Write, diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def index 9223f62b3639..f234488eaa80 100644 --- a/clang/include/clang/Basic/Sanitizers.def +++ b/clang/include/clang/Basic/Sanitizers.def @@ -73,6 +73,9 @@ SANITIZER("fuzzer", Fuzzer) // libFuzzer-required instrumentation, no linking. SANITIZER("fuzzer-no-link", FuzzerNoLink) +// TypeSanitizer +SANITIZER("type", Type) + // ThreadSanitizer SANITIZER("thread", Thread) diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 89f5a76eb113..31280df93e4c 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -308,6 +308,13 @@ def OpenACCAssociatedStmtConstruct def OpenACCComputeConstruct : StmtNode<OpenACCAssociatedStmtConstruct>; def OpenACCLoopConstruct : StmtNode<OpenACCAssociatedStmtConstruct>; def OpenACCCombinedConstruct : StmtNode<OpenACCAssociatedStmtConstruct>; +def OpenACCDataConstruct : StmtNode<OpenACCAssociatedStmtConstruct>; +def OpenACCEnterDataConstruct : StmtNode<OpenACCConstructStmt>; +def OpenACCExitDataConstruct : StmtNode<OpenACCConstructStmt>; +def OpenACCHostDataConstruct : StmtNode<OpenACCAssociatedStmtConstruct>; +def OpenACCWaitConstruct : StmtNode<OpenACCConstructStmt>; +def OpenACCInitConstruct : StmtNode<OpenACCConstructStmt>; +def OpenACCShutdownConstruct : StmtNode<OpenACCConstructStmt>; // OpenACC Additional Expressions. def OpenACCAsteriskSizeExpr : StmtNode<Expr>; diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 4420228793e9..f2905f30a7c3 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -358,7 +358,14 @@ public: // void *__saved_reg_area_end_pointer; // void *__overflow_area_pointer; //} va_list; - HexagonBuiltinVaList + HexagonBuiltinVaList, + + // typedef struct __va_list_tag { + // int* __va_stk; + // int* __va_reg; + // int __va_ndx; + //} va_list; + XtensaABIBuiltinVaList }; protected: @@ -1009,7 +1016,6 @@ public: virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const = 0; - /// Return information about target-specific builtins for /// the current primary target, and info about which builtins are non-portable /// across the current set of primary and secondary targets. diff --git a/clang/include/clang/Basic/arm_immcheck_incl.td b/clang/include/clang/Basic/arm_immcheck_incl.td index 9d7f74a35aaa..6892b8299771 100644 --- a/clang/include/clang/Basic/arm_immcheck_incl.td +++ b/clang/include/clang/Basic/arm_immcheck_incl.td @@ -2,7 +2,9 @@ class ImmCheckType<int val> { int Value = val; } -// These must be kept in sync with the flags in include/clang/Basic/TargetBuiltins.h + +// For SVE, container_size refers to the width of a vector segment (128b). +// For NEON, container_size refers to the vector width (64b or 128b). def ImmCheck0_31 : ImmCheckType<0>; // 0..31 (used for e.g. predicate patterns) def ImmCheck1_16 : ImmCheckType<1>; // 1..16 def ImmCheckExtract : ImmCheckType<2>; // 0..(2048/sizeinbits(elt) - 1) @@ -10,10 +12,10 @@ def ImmCheckShiftRight : ImmCheckType<3>; // 1..sizeinbits(elt) def ImmCheckShiftRightNarrow : ImmCheckType<4>; // 1..sizeinbits(elt)/2 def ImmCheckShiftLeft : ImmCheckType<5>; // 0..(sizeinbits(elt) - 1) def ImmCheck0_7 : ImmCheckType<6>; // 0..7 -def ImmCheckLaneIndex : ImmCheckType<7>; // 0..(sizeinbits(vec)/(sizeinbits(elt)) - 1) +def ImmCheckLaneIndex : ImmCheckType<7>; // 0..(container_size/(sizeinbits(elt)) - 1) def ImmCheckCvt : ImmCheckType<8>; // 1..sizeinbits(elt) (same as ShiftRight) -def ImmCheckLaneIndexCompRotate : ImmCheckType<9>; // 0..(sizeinbits(vec)/(2*sizeinbits(elt)) - 1) -def ImmCheckLaneIndexDot : ImmCheckType<10>; // 0..(sizeinbits(vec)/(4*sizeinbits(elt)) - 1) +def ImmCheckLaneIndexCompRotate : ImmCheckType<9>; // 0..(container_size/(2*sizeinbits(elt)) - 1) +def ImmCheckLaneIndexDot : ImmCheckType<10>; // 0..(container_size/(4*sizeinbits(elt)) - 1) def ImmCheckComplexRot90_270 : ImmCheckType<11>; // [90,270] def ImmCheckComplexRotAll90 : ImmCheckType<12>; // [0, 90, 180,270] def ImmCheck0_13 : ImmCheckType<13>; // 0..13 diff --git a/clang/include/clang/Basic/arm_mve.td b/clang/include/clang/Basic/arm_mve.td index 93abbc47c54d..6dd8c52ddfd7 100644 --- a/clang/include/clang/Basic/arm_mve.td +++ b/clang/include/clang/Basic/arm_mve.td @@ -1270,13 +1270,13 @@ defm sqrshr: ScalarSaturatingShiftReg<s32, s64>; def lsll: LongScalarShift<u64, (args s32:$sh), (IRInt<"lsll"> $lo, $hi, $sh)>; def asrl: LongScalarShift<s64, (args s32:$sh), (IRInt<"asrl"> $lo, $hi, $sh)>; -multiclass vadcsbc { +multiclass vadcsbc<dag initial_carry_in> { def q: Intrinsic<Vector, (args Vector:$a, Vector:$b, Ptr<uint>:$carry), (seq (IRInt<NAME, [Vector]> $a, $b, (shl (load $carry), 29)):$pair, (store (and 1, (lshr (xval $pair, 1), 29)), $carry), (xval $pair, 0))>; def iq: Intrinsic<Vector, (args Vector:$a, Vector:$b, Ptr<uint>:$carry), - (seq (IRInt<NAME, [Vector]> $a, $b, 0):$pair, + (seq (IRInt<NAME, [Vector]> $a, $b, initial_carry_in):$pair, (store (and 1, (lshr (xval $pair, 1), 29)), $carry), (xval $pair, 0))>; def q_m: Intrinsic<Vector, (args Vector:$inactive, Vector:$a, Vector:$b, @@ -1288,13 +1288,13 @@ multiclass vadcsbc { def iq_m: Intrinsic<Vector, (args Vector:$inactive, Vector:$a, Vector:$b, Ptr<uint>:$carry, Predicate:$pred), (seq (IRInt<NAME # "_predicated", [Vector, Predicate]> $inactive, $a, $b, - 0, $pred):$pair, + initial_carry_in, $pred):$pair, (store (and 1, (lshr (xval $pair, 1), 29)), $carry), (xval $pair, 0))>; } let params = T.Int32 in { - defm vadc: vadcsbc; - defm vsbc: vadcsbc; + defm vadc: vadcsbc<(u32 0)>; + defm vsbc: vadcsbc<(shl 1, 29)>; } let params = T.Int in { diff --git a/clang/include/clang/Basic/arm_sme.td b/clang/include/clang/Basic/arm_sme.td index 0f689e82bdb7..6b31dec004a1 100644 --- a/clang/include/clang/Basic/arm_sme.td +++ b/clang/include/clang/Basic/arm_sme.td @@ -740,6 +740,38 @@ let SMETargetGuard = "sme2" in { def SVLUTI4_LANE_ZT_X2 : Inst<"svluti4_lane_zt_{d}_x2", "2.di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt_x2", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_3>]>; } +// +// SME2 FP8 instructions +// + +// FDOT +let SMETargetGuard = "sme-f8f32" in { + def SVDOT_LANE_FP8_ZA32_VG1x2 : Inst<"svdot_lane_za32[_mf8]_vg1x2_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za32_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_3>]>; + def SVDOT_LANE_FP8_ZA32_VG1x4 : Inst<"svdot_lane_za32[_mf8]_vg1x4_fpm", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za32_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_3>]>; + + def SVVDOTB_LANE_FP8_ZA32_VG1x4 : Inst<"svvdotb_lane_za32[_mf8]_vg1x4_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fvdotb_lane_za32_vg1x4", [IsOverloadNone, IsStreaming, IsInOutZA, SetsFPMR], [ImmCheck<3, ImmCheck0_3>]>; + def SVVDOTT_LANE_FP8_ZA32_VG1x4 : Inst<"svvdott_lane_za32[_mf8]_vg1x4_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fvdott_lane_za32_vg1x4", [IsOverloadNone, IsStreaming, IsInOutZA, SetsFPMR], [ImmCheck<3, ImmCheck0_3>]>; + + def SVDOT_SINGLE_FP8_ZA32_VG1x2 : Inst<"svdot[_single]_za32[_mf8]_vg1x2_fpm", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za32_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + def SVDOT_SINGLE_FP8_ZA32_VG1x4 : Inst<"svdot[_single]_za32[_mf8]_vg1x4_fpm", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za32_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + + def SVDOT_MULTI_FP8_ZA32_VG1x2 : Inst<"svdot_za32[_mf8]_vg1x2_fpm", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za32_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + def SVDOT_MULTI_FP8_ZA32_VG1x4 : Inst<"svdot_za32[_mf8]_vg1x4_fpm", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za32_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; +} + +let SMETargetGuard = "sme-f8f16" in { + def SVDOT_LANE_FP8_ZA16_VG1x2 : Inst<"svdot_lane_za16[_mf8]_vg1x2_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za16_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_7>]>; + def SVDOT_LANE_FP8_ZA16_VG1x4 : Inst<"svdot_lane_za16[_mf8]_vg1x4_fpm", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za16_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_7>]>; + + def SVVDOT_LANE_FP8_ZA16_VG1x2 : Inst<"svvdot_lane_za16[_mf8]_vg1x2_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fvdot_lane_za16_vg1x2", [IsOverloadNone, IsStreaming, IsInOutZA, SetsFPMR], [ImmCheck<3, ImmCheck0_7>]>; + + def SVDOT_SINGLE_FP8_ZA16_VG1x2 : Inst<"svdot[_single]_za16[_mf8]_vg1x2_fpm", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za16_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + def SVDOT_SINGLE_FP8_ZA16_VG1x4 : Inst<"svdot[_single]_za16[_mf8]_vg1x4_fpm", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za16_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + + def SVDOT_MULTI_FP8_ZA16_VG1x2 : Inst<"svdot_za16[_mf8]_vg1x2_fpm", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za16_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + def SVDOT_MULTI_FP8_ZA16_VG1x4 : Inst<"svdot_za16[_mf8]_vg1x4_fpm", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za16_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; +} + //////////////////////////////////////////////////////////////////////////////// // SME2p1 - FMOPA, FMOPS (non-widening) let SMETargetGuard = "sme-b16b16" in { @@ -824,4 +856,52 @@ let SMETargetGuard = "sme-lutv2" in { def SVLUTI4_ZT_X4 : SInst<"svluti4_zt_{d}_x4", "4i2.u", "cUc", MergeNone, "aarch64_sme_luti4_zt_x4", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>]>; } +let SMETargetGuard = "sme-f8f32" in { + def SVMOPA_FP8_ZA32 : Inst<"svmopa_za32[_mf8]_m_fpm", "viPPdd>", "m", MergeNone, "aarch64_sme_fp8_fmopa_za32", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_3>]>; + // FMLALL (indexed) + def SVMLA_FP8_LANE_ZA32_VG4x1 : Inst<"svmla_lane_za32[_mf8]_vg4x1_fpm", "vmddi>", "m", MergeNone, "aarch64_sme_fp8_fmlall_lane_za32_vg4x1", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>; + def SVMLA_FP8_LANE_ZA32_VG4x2 : Inst<"svmla_lane_za32[_mf8]_vg4x2_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fmlall_lane_za32_vg4x2", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>; + def SVMLA_FP8_LANE_ZA16_VG4x4 : Inst<"svmla_lane_za32[_mf8]_vg4x4_fpm", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fmlall_lane_za32_vg4x4", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>; + // FMLALL (single) + def SVMLA_FP8_SINGLE_ZA32_VG4x1 : Inst<"svmla[_single]_za32[_mf8]_vg4x1_fpm", "vmdd>", "m", MergeNone, "aarch64_sme_fp8_fmlall_single_za32_vg4x1", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + def SVMLA_FP8_SINGLE_ZA32_VG4x2 : Inst<"svmla[_single]_za32[_mf8]_vg4x2_fpm", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fmlall_single_za32_vg4x2", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + def SVMLA_FP8_SINGLE_ZA32_VG4x4 : Inst<"svmla[_single]_za32[_mf8]_vg4x4_fpm", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fmlall_single_za32_vg4x4", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + // FMLALL (multiple) + def SVMLA_FP8_MULTI_ZA32_VG4x2 : Inst<"svmla_za32[_mf8]_vg4x2_fpm", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fmlall_multi_za32_vg4x2", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + def SVMLA_FP8_MULTI_ZA32_VG4x4 : Inst<"svmla_za32[_mf8]_vg4x4_fpm", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fmlall_multi_za32_vg4x4", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; +} + +let SMETargetGuard = "sme-f8f16" in { + def SVMOPA_FP8_ZA16 : Inst<"svmopa_za16[_mf8]_m_fpm", "viPPdd>", "m", MergeNone, "aarch64_sme_fp8_fmopa_za16", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_1>]>; + // FMLAL (indexed) + def SVMLA_FP8_LANE_ZA16_VG2x1 : Inst<"svmla_lane_za16[_mf8]_vg2x1_fpm", "vmddi>", "m", MergeNone, "aarch64_sme_fp8_fmlal_lane_za16_vg2x1", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>; + def SVMLA_FP8_LANE_ZA16_VG2x2 : Inst<"svmla_lane_za16[_mf8]_vg2x2_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fmlal_lane_za16_vg2x2", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>; + def SVMLA_FP8_LANE_ZA16_VG2x4 : Inst<"svmla_lane_za16[_mf8]_vg2x4_fpm", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fmlal_lane_za16_vg2x4", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>; + // FMLAL (single) + def SVMLA_FP8_SINGLE_ZA16_VG2x1 : Inst<"svmla[_single]_za16[_mf8]_vg2x1_fpm", "vmdd>", "m", MergeNone, "aarch64_sme_fp8_fmlal_single_za16_vg2x1", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + def SVMLA_FP8_SINGLE_ZA16_VG2x2 : Inst<"svmla[_single]_za16[_mf8]_vg2x2_fpm", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fmlal_single_za16_vg2x2", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + def SVMLA_FP8_SINGLE_ZA16_VG2x4 : Inst<"svmla[_single]_za16[_mf8]_vg2x4_fpm", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fmlal_single_za16_vg2x4", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + // FMLAL (multiple) + def SVMLA_FP8_MULTI_ZA16_VG2x2 : Inst<"svmla_za16[_mf8]_vg2x2_fpm", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fmlal_multi_za16_vg2x2", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; + def SVMLA_FP8_MULTI_ZA16_VG2x4 : Inst<"svmla_za16[_mf8]_vg2x4_fpm", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fmlal_multi_za16_vg2x4", + [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; +} + } // let SVETargetGuard = InvalidMode diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td index e551d6e46b8f..1c6bdb8cad2d 100644 --- a/clang/include/clang/Basic/arm_sve.td +++ b/clang/include/clang/Basic/arm_sve.td @@ -463,18 +463,19 @@ let SVETargetGuard = "sve,bf16", SMETargetGuard = "sme,bf16" in { let SVETargetGuard = "sve2p1", SMETargetGuard = InvalidMode in { // Contiguous truncating store from quadword (single vector). - def SVST1UWQ : MInst<"svst1wq[_{d}]", "vPcd", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1wq">; - def SVST1UWQ_VNUM : MInst<"svst1wq_vnum[_{d}]", "vPcld", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1wq">; + def SVST1UWQ : MInst<"svst1wq[_{d}]", "vPpd", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1wq">; + def SVST1UWQ_VNUM : MInst<"svst1wq_vnum[_{d}]", "vPpld", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1wq">; - def SVST1UDQ : MInst<"svst1dq[_{d}]", "vPcd", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1dq">; - def SVST1UDQ_VNUM : MInst<"svst1dq_vnum[_{d}]", "vPcld", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1dq">; + def SVST1UDQ : MInst<"svst1dq[_{d}]", "vPpd", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1dq">; + def SVST1UDQ_VNUM : MInst<"svst1dq_vnum[_{d}]", "vPpld", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1dq">; // Store one vector (vector base + scalar offset) def SVST1Q_SCATTER_U64BASE_OFFSET : MInst<"svst1q_scatter[_{2}base]_offset[_{d}]", "vPgld", "cUcsUsiUilUlfhdb", [IsScatterStore, IsByteIndexed], MemEltTyDefault, "aarch64_sve_st1q_scatter_scalar_offset">; def SVST1Q_SCATTER_U64BASE : MInst<"svst1q_scatter[_{2}base][_{d}]", "vPgd", "cUcsUsiUilUlfhdb", [IsScatterStore, IsByteIndexed], MemEltTyDefault, "aarch64_sve_st1q_scatter_scalar_offset">; // Store one vector (scalar base + vector offset) - def SVST1Q_SCATTER_U64OFFSET : MInst<"svst1q_scatter_[{3}]offset[_{d}]", "vPpgd", "cUcsUsiUilUlfhdb", [IsScatterStore, IsByteIndexed], MemEltTyDefault, "aarch64_sve_st1q_scatter_vector_offset">; + def SVST1Q_SCATTER_OFFSETS_U : MInst<"svst1q_scatter_[{3}]offset[_{d}]", "vPpgd", "cUcsUsiUilUlfhdb", [IsScatterStore, IsByteIndexed], MemEltTyDefault, "aarch64_sve_st1q_scatter_vector_offset">; + def SVST1Q_SCATTER_OFFSETS_S : MInst<"svst1q_scatter_[{3}]offset[_{d}]", "vPp#d", "cUcsUsiUilUlfhdb", [IsScatterStore, IsByteIndexed], MemEltTyDefault, "aarch64_sve_st1q_scatter_vector_offset">; // Store N vectors into N-element structure (scalar base) defm SVST2Q : StructStore<"svst2q[_{d}]", "vPc2", "aarch64_sve_st2q">; @@ -488,6 +489,7 @@ let SVETargetGuard = "sve2p1", SMETargetGuard = InvalidMode in { // Scatter store quadwords (scalar base + vector index) def SVST1Q_SCATTER_INDICES_U : MInst<"svst1q_scatter_[{3}]index[_{d}]", "vPpgd", "sUsiUilUlbhfd", [IsScatterStore], MemEltTyDefault, "aarch64_sve_st1q_scatter_index">; + def SVST1Q_SCATTER_INDICES_S : MInst<"svst1q_scatter_[{3}]index[_{d}]", "vPp#d", "sUsiUilUlbhfd", [IsScatterStore], MemEltTyDefault, "aarch64_sve_st1q_scatter_index">; // Scatter store quadwords (vector base + scalar index) def SVST1Q_SCATTER_INDEX_S : MInst<"svst1q_scatter[_{2}base]_index[_{d}]", "vPgld", "sUsiUilUlbhfd", [IsScatterStore], MemEltTyDefault, "aarch64_sve_st1q_scatter_scalar_offset">; @@ -2429,9 +2431,19 @@ let SVETargetGuard = InvalidMode, SMETargetGuard = "sme2,fp8" in { def FSCALE_X2 : Inst<"svscale[_{d}_x2]", "222.x", "fhd", MergeNone, "aarch64_sme_fp8_scale_x2", [IsStreaming],[]>; def FSCALE_X4 : Inst<"svscale[_{d}_x4]", "444.x", "fhd", MergeNone, "aarch64_sme_fp8_scale_x4", [IsStreaming],[]>; + // Convert from FP8 to half-precision/BFloat16 multi-vector + def SVF1CVT_X2 : Inst<"svcvt1_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvt1_x2", [IsStreaming, SetsFPMR], []>; + def SVF2CVT_X2 : Inst<"svcvt2_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvt2_x2", [IsStreaming, SetsFPMR], []>; + // Convert from FP8 to deinterleaved half-precision/BFloat16 multi-vector - def SVF1CVTL : Inst<"svcvtl1_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvtl1_x2", [IsStreaming, SetsFPMR], []>; - def SVF2CVTL : Inst<"svcvtl2_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvtl2_x2", [IsStreaming, SetsFPMR], []>; + def SVF1CVTL_X2 : Inst<"svcvtl1_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvtl1_x2", [IsStreaming, SetsFPMR], []>; + def SVF2CVTL_X2 : Inst<"svcvtl2_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvtl2_x2", [IsStreaming, SetsFPMR], []>; + + // Convert from single/half/bfloat multivector to FP8 + def SVFCVT_X2 : Inst<"svcvt_mf8[_{d}_x2]_fpm", "~2>", "bh", MergeNone, "aarch64_sve_fp8_cvt_x2", [IsStreaming, SetsFPMR], []>; + def SVFCVT_X4 : Inst<"svcvt_mf8[_{d}_x4]_fpm", "~4>", "f", MergeNone, "aarch64_sve_fp8_cvt_x4", [IsOverloadNone, IsStreaming, SetsFPMR], []>; + // interleaved + def SVFCVTN_X4 : Inst<"svcvtn_mf8[_{d}_x4]_fpm", "~4>", "f", MergeNone, "aarch64_sve_fp8_cvtn_x4", [IsOverloadNone, IsStreaming, SetsFPMR], []>; } let SVETargetGuard = "sve2p1", SMETargetGuard = "sme2" in { @@ -2447,3 +2459,72 @@ let SVETargetGuard = "sve2,faminmax", SMETargetGuard = "sme2,faminmax" in { defm SVAMIN : SInstZPZZ<"svamin", "hfd", "aarch64_sve_famin", "aarch64_sve_famin_u">; defm SVAMAX : SInstZPZZ<"svamax", "hfd", "aarch64_sve_famax", "aarch64_sve_famax_u">; } + +let SVETargetGuard = "sve2,fp8", SMETargetGuard = "sme2,fp8" in { + // SVE FP8 widening conversions + + // 8-bit floating-point convert to BFloat16/Float16 + def SVF1CVT : SInst<"svcvt1_{d}[_mf8]_fpm", "d~>", "bh", MergeNone, "aarch64_sve_fp8_cvt1", [VerifyRuntimeMode, SetsFPMR]>; + def SVF2CVT : SInst<"svcvt2_{d}[_mf8]_fpm", "d~>", "bh", MergeNone, "aarch64_sve_fp8_cvt2", [VerifyRuntimeMode, SetsFPMR]>; + + // 8-bit floating-point convert to BFloat16/Float16 (top) + def SVF1CVTLT : SInst<"svcvtlt1_{d}[_mf8]_fpm", "d~>", "bh", MergeNone, "aarch64_sve_fp8_cvtlt1", [VerifyRuntimeMode, SetsFPMR]>; + def SVF2CVTLT : SInst<"svcvtlt2_{d}[_mf8]_fpm", "d~>", "bh", MergeNone, "aarch64_sve_fp8_cvtlt2", [VerifyRuntimeMode, SetsFPMR]>; + + // BFloat16/Float16 convert, narrow and interleave to 8-bit floating-point + def SVFCVTN : SInst<"svcvtn_mf8[_{d}_x2]_fpm", "~2>", "bh", MergeNone, "aarch64_sve_fp8_cvtn", [VerifyRuntimeMode, SetsFPMR]>; + + // Single-precision convert, narrow and interleave to 8-bit floating-point (top and bottom) + def SVFCVTNB : SInst<"svcvtnb_mf8[_f32_x2]_fpm", "~2>", "f", MergeNone, "aarch64_sve_fp8_cvtnb", [VerifyRuntimeMode, SetsFPMR]>; + def SVFCVTNT : SInst<"svcvtnt_mf8[_f32_x2]_fpm", "~~2>", "f", MergeNone, "aarch64_sve_fp8_cvtnt", [VerifyRuntimeMode, SetsFPMR]>; +} + +let SVETargetGuard = "sve2,fp8dot2", SMETargetGuard ="sme,ssve-fp8dot2" in { + // 8-bit floating-point dot product to half-precision (vectors) + def SVFDOT_2WAY : SInst<"svdot[_f16_mf8]_fpm", "dd~~>", "h", MergeNone, "aarch64_sve_fp8_fdot", [VerifyRuntimeMode, SetsFPMR]>; + def SVFDOT_N_2WAY : SInst<"svdot[_n_f16_mf8]_fpm", "dd~!>", "h", MergeNone, "aarch64_sve_fp8_fdot", [VerifyRuntimeMode, SetsFPMR]>; + + // 8-bit floating-point dot product to half-precision (indexed) + def SVFDOT_LANE_2WAY : SInst<"svdot_lane[_f16_mf8]_fpm", "dd~~i>", "h", MergeNone, "aarch64_sve_fp8_fdot_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_7>]>; +} + +let SVETargetGuard = "sve2,fp8dot4", SMETargetGuard ="sme,ssve-fp8dot4" in { + // 8-bit floating-point dot product to single-precision (vectors) + def SVFDOT_4WAY : SInst<"svdot[_f32_mf8]_fpm", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fdot", [VerifyRuntimeMode, SetsFPMR]>; + def SVFDOT_N_4WAY : SInst<"svdot[_n_f32_mf8]_fpm", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fdot", [VerifyRuntimeMode, SetsFPMR]>; + + // 8-bit floating-point dot product to single-precision (indexed) + def SVFDOT_LANE_4WAY : SInst<"svdot_lane[_f32_mf8]_fpm", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fdot_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_3>]>; +} + +let SVETargetGuard = "sve2,fp8fma", SMETargetGuard = "sme,ssve-fp8fma" in { + // 8-bit floating-point multiply-add long to half-precision (bottom) + def SVFMLALB : SInst<"svmlalb[_f16_mf8]_fpm", "dd~~>", "h", MergeNone, "aarch64_sve_fp8_fmlalb", [VerifyRuntimeMode, SetsFPMR]>; + def SVFMLALB_N : SInst<"svmlalb[_n_f16_mf8]_fpm", "dd~!>", "h", MergeNone, "aarch64_sve_fp8_fmlalb", [VerifyRuntimeMode, SetsFPMR]>; + + // 8-bit floating-point multiply-add long to ha_fpmlf-precision (bottom, indexed) + def SVFMLALB_LANE : SInst<"svmlalb_lane[_f16_mf8]_fpm", "dd~~i>", "h", MergeNone, "aarch64_sve_fp8_fmlalb_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_15>]>; + + // 8-bit floating-point multiply-add long to half-precision (top) + def SVFMLALT : SInst<"svmlalt[_f16_mf8]_fpm", "dd~~>", "h", MergeNone, "aarch64_sve_fp8_fmlalt", [VerifyRuntimeMode, SetsFPMR]>; + def SVFMLALT_N : SInst<"svmlalt[_n_f16_mf8]_fpm", "dd~!>", "h", MergeNone, "aarch64_sve_fp8_fmlalt", [VerifyRuntimeMode, SetsFPMR]>; + + // 8-bit floating-point multiply-add long to half-precision (top, indexed) + def SVFMLALT_LANE : SInst<"svmlalt_lane[_f16_mf8]_fpm", "dd~~i>", "h", MergeNone, "aarch64_sve_fp8_fmlalt_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_15>]>; + + // 8-bit floating-point multiply-add long long to single-precision (all top/bottom variants) + def SVFMLALLBB : SInst<"svmlallbb[_f32_mf8]_fpm", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fmlallbb", [VerifyRuntimeMode, SetsFPMR]>; + def SVFMLALLBB_N : SInst<"svmlallbb[_n_f32_mf8]_fpm", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fmlallbb", [VerifyRuntimeMode, SetsFPMR]>; + def SVFMLALLBT : SInst<"svmlallbt[_f32_mf8]_fpm", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fmlallbt", [VerifyRuntimeMode, SetsFPMR]>; + def SVFMLALLBT_N : SInst<"svmlallbt[_n_f32_mf8]_fpm", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fmlallbt", [VerifyRuntimeMode, SetsFPMR]>; + def SVFMLALLTB : SInst<"svmlalltb[_f32_mf8]_fpm", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fmlalltb", [VerifyRuntimeMode, SetsFPMR]>; + def SVFMLALLTB_N : SInst<"svmlalltb[_n_f32_mf8]_fpm", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fmlalltb", [VerifyRuntimeMode, SetsFPMR]>; + def SVFMLALLTT : SInst<"svmlalltt[_f32_mf8]_fpm", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fmlalltt", [VerifyRuntimeMode, SetsFPMR]>; + def SVFMLALLTT_N : SInst<"svmlalltt[_n_f32_mf8]_fpm", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fmlalltt", [VerifyRuntimeMode, SetsFPMR]>; + + // 8-bit floating-point multiply-add long long to single-precision (indexed, all top/bottom variants) + def SVFMLALLBB_LANE : SInst<"svmlallbb_lane[_f32_mf8]_fpm", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fmlallbb_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_7>]>; + def SVFMLALLBT_LANE : SInst<"svmlallbt_lane[_f32_mf8]_fpm", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fmlallbt_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_7>]>; + def SVFMLALLTB_LANE : SInst<"svmlalltb_lane[_f32_mf8]_fpm", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fmlalltb_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_7>]>; + def SVFMLALLTT_LANE : SInst<"svmlalltt_lane[_f32_mf8]_fpm", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fmlalltt_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_7>]>; +} diff --git a/clang/include/clang/Basic/arm_sve_sme_incl.td b/clang/include/clang/Basic/arm_sve_sme_incl.td index de10be7bdce0..13e7cf45471c 100644 --- a/clang/include/clang/Basic/arm_sve_sme_incl.td +++ b/clang/include/clang/Basic/arm_sve_sme_incl.td @@ -52,6 +52,7 @@ include "arm_immcheck_incl.td" // h: half-float // d: double // b: bfloat +// m: mfloat8 // Typespec modifiers // ------------------ @@ -69,6 +70,7 @@ include "arm_immcheck_incl.td" // x: vector of signed integers // u: vector of unsigned integers // d: default +// p: pointer type // c: const pointer type // P: predicate type // s: scalar of element type @@ -88,6 +90,7 @@ include "arm_immcheck_incl.td" // j: element type promoted to 64bits (splat to vector type) // K: element type bitcast to a signed integer (splat to vector type) // L: element type bitcast to an unsigned integer (splat to vector type) +// !: mfloat8_t (splat to svmfloat8_t) // // i: constant uint64_t // k: int32_t @@ -99,6 +102,7 @@ include "arm_immcheck_incl.td" // [: svuint8_t // t: svint32_t // z: svuint32_t +// #: svint64_t // g: svuint64_t // O: svfloat16_t // M: svfloat32_t diff --git a/clang/include/clang/CIR/CIRGenerator.h b/clang/include/clang/CIR/CIRGenerator.h index c8ca7e4bfa72..414eba80b88b 100644 --- a/clang/include/clang/CIR/CIRGenerator.h +++ b/clang/include/clang/CIR/CIRGenerator.h @@ -37,14 +37,14 @@ namespace cir { class CIRGenerator : public clang::ASTConsumer { virtual void anchor(); clang::DiagnosticsEngine &diags; - clang::ASTContext *astCtx; + clang::ASTContext *astContext; // Only used for debug info. llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs; const clang::CodeGenOptions &codeGenOpts; protected: - std::unique_ptr<mlir::MLIRContext> mlirCtx; + std::unique_ptr<mlir::MLIRContext> mlirContext; std::unique_ptr<clang::CIRGen::CIRGenModule> cgm; public: @@ -52,7 +52,7 @@ public: llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs, const clang::CodeGenOptions &cgo); ~CIRGenerator() override; - void Initialize(clang::ASTContext &astCtx) override; + void Initialize(clang::ASTContext &astContext) override; bool HandleTopLevelDecl(clang::DeclGroupRef group) override; mlir::ModuleOp getModule() const; }; diff --git a/clang/include/clang/CIR/CMakeLists.txt b/clang/include/clang/CIR/CMakeLists.txt index f8d6f407a03d..e20c896171c9 100644 --- a/clang/include/clang/CIR/CMakeLists.txt +++ b/clang/include/clang/CIR/CMakeLists.txt @@ -4,3 +4,4 @@ include_directories(${MLIR_INCLUDE_DIR}) include_directories(${MLIR_TABLEGEN_OUTPUT_DIR}) add_subdirectory(Dialect) +add_subdirectory(Interfaces) diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h new file mode 100644 index 000000000000..b4a961de224a --- /dev/null +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H +#define LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H + +#include "clang/CIR/Dialect/IR/CIRAttrs.h" + +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/Types.h" + +namespace cir { + +class CIRBaseBuilderTy : public mlir::OpBuilder { + +public: + CIRBaseBuilderTy(mlir::MLIRContext &mlirContext) + : mlir::OpBuilder(&mlirContext) {} + + cir::PointerType getPointerTo(mlir::Type ty) { + return cir::PointerType::get(getContext(), ty); + } + + cir::PointerType getVoidPtrTy() { + return getPointerTo(cir::VoidType::get(getContext())); + } + + mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) { + auto valueAttr = mlir::IntegerAttr::get( + mlir::IntegerType::get(type.getContext(), 64), value); + return cir::ConstPtrAttr::get( + getContext(), mlir::cast<cir::PointerType>(type), valueAttr); + } +}; + +} // namespace cir + +#endif diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h new file mode 100644 index 000000000000..438fb7d09608 --- /dev/null +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the attributes in the CIR dialect. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CIR_DIALECT_IR_CIRATTRS_H +#define LLVM_CLANG_CIR_DIALECT_IR_CIRATTRS_H + +#include "clang/CIR/Dialect/IR/CIRTypes.h" + +#include "mlir/IR/Attributes.h" +#include "mlir/IR/BuiltinAttributeInterfaces.h" + +#include "llvm/ADT/SmallVector.h" + +//===----------------------------------------------------------------------===// +// CIR Dialect Attrs +//===----------------------------------------------------------------------===// + +namespace clang { +class FunctionDecl; +class VarDecl; +class RecordDecl; +} // namespace clang + +#define GET_ATTRDEF_CLASSES +#include "clang/CIR/Dialect/IR/CIROpsAttributes.h.inc" + +#endif // LLVM_CLANG_CIR_DIALECT_IR_CIRATTRS_H diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td new file mode 100644 index 000000000000..bd1665e1ac1a --- /dev/null +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -0,0 +1,142 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the CIR dialect attributes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CIR_DIALECT_IR_CIRATTRS_TD +#define LLVM_CLANG_CIR_DIALECT_IR_CIRATTRS_TD + +include "mlir/IR/BuiltinAttributeInterfaces.td" +include "mlir/IR/EnumAttr.td" + +include "clang/CIR/Dialect/IR/CIRDialect.td" + +//===----------------------------------------------------------------------===// +// CIR Attrs +//===----------------------------------------------------------------------===// + +class CIR_Attr<string name, string attrMnemonic, list<Trait> traits = []> + : AttrDef<CIR_Dialect, name, traits> { + let mnemonic = attrMnemonic; +} + +class CIRUnitAttr<string name, string attrMnemonic, list<Trait> traits = []> + : CIR_Attr<name, attrMnemonic, traits> { + let returnType = "bool"; + let defaultValue = "false"; + let valueType = NoneType; + let isOptional = 1; +} + +//===----------------------------------------------------------------------===// +// IntegerAttr +//===----------------------------------------------------------------------===// + +def IntAttr : CIR_Attr<"Int", "int", [TypedAttrInterface]> { + let summary = "An attribute containing an integer value"; + let description = [{ + An integer attribute is a literal attribute that represents an integral + value of the specified integer type. + }]; + let parameters = (ins AttributeSelfTypeParameter<"">:$type, + "llvm::APInt":$value); + let builders = [ + AttrBuilderWithInferredContext<(ins "mlir::Type":$type, + "const llvm::APInt &":$value), [{ + return $_get(type.getContext(), type, value); + }]>, + AttrBuilderWithInferredContext<(ins "mlir::Type":$type, + "int64_t":$value), [{ + IntType intType = mlir::cast<IntType>(type); + mlir::APInt apValue(intType.getWidth(), value, intType.isSigned()); + return $_get(intType.getContext(), intType, apValue); + }]>, + ]; + let extraClassDeclaration = [{ + int64_t getSInt() const { return getValue().getSExtValue(); } + uint64_t getUInt() const { return getValue().getZExtValue(); } + bool isNullValue() const { return getValue() == 0; } + uint64_t getBitWidth() const { + return mlir::cast<IntType>(getType()).getWidth(); + } + }]; + let genVerifyDecl = 1; + let hasCustomAssemblyFormat = 1; +} + +//===----------------------------------------------------------------------===// +// FPAttr +//===----------------------------------------------------------------------===// + +def FPAttr : CIR_Attr<"FP", "fp", [TypedAttrInterface]> { + let summary = "An attribute containing a floating-point value"; + let description = [{ + An fp attribute is a literal attribute that represents a floating-point + value of the specified floating-point type. Supporting only CIR FP types. + }]; + let parameters = (ins + AttributeSelfTypeParameter<"", "::cir::CIRFPTypeInterface">:$type, + APFloatParameter<"">:$value + ); + let builders = [ + AttrBuilderWithInferredContext<(ins "mlir::Type":$type, + "const llvm::APFloat &":$value), [{ + return $_get(type.getContext(), mlir::cast<CIRFPTypeInterface>(type), + value); + }]>, + AttrBuilder<(ins "mlir::Type":$type, + "const llvm::APFloat &":$value), [{ + return $_get($_ctxt, mlir::cast<CIRFPTypeInterface>(type), value); + }]>, + ]; + let extraClassDeclaration = [{ + static FPAttr getZero(mlir::Type type); + }]; + let genVerifyDecl = 1; + + let assemblyFormat = [{ + `<` custom<FloatLiteral>($value, ref($type)) `>` + }]; +} + +//===----------------------------------------------------------------------===// +// ConstPtrAttr +//===----------------------------------------------------------------------===// + +def ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", [TypedAttrInterface]> { + let summary = "Holds a constant pointer value"; + let parameters = (ins + AttributeSelfTypeParameter<"", "::cir::PointerType">:$type, + "mlir::IntegerAttr":$value); + let description = [{ + A pointer attribute is a literal attribute that represents an integral + value of a pointer type. + }]; + let builders = [ + AttrBuilderWithInferredContext<(ins "mlir::Type":$type, + "mlir::IntegerAttr":$value), [{ + return $_get(type.getContext(), mlir::cast<cir::PointerType>(type), + value); + }]>, + AttrBuilder<(ins "mlir::Type":$type, + "mlir::IntegerAttr":$value), [{ + return $_get($_ctxt, mlir::cast<cir::PointerType>(type), value); + }]>, + ]; + let extraClassDeclaration = [{ + bool isNullValue() const { return getValue().getInt() == 0; } + }]; + + let assemblyFormat = [{ + `<` custom<ConstPtr>($value) `>` + }]; +} + +#endif // LLVM_CLANG_CIR_DIALECT_IR_CIRATTRS_TD diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h index 0b71bdad29a3..683176b139ca 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h @@ -26,6 +26,7 @@ #include "mlir/Interfaces/MemorySlotInterfaces.h" #include "mlir/Interfaces/SideEffectInterfaces.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" #include "clang/CIR/Dialect/IR/CIROpsDialect.h.inc" // TableGen'erated files for MLIR dialects require that a macro be defined when diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 4462eb6fc00b..b15e0415360e 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -15,6 +15,8 @@ #define LLVM_CLANG_CIR_DIALECT_IR_CIROPS include "clang/CIR/Dialect/IR/CIRDialect.td" +include "clang/CIR/Dialect/IR/CIRTypes.td" +include "clang/CIR/Dialect/IR/CIRAttrs.td" include "mlir/IR/BuiltinAttributeInterfaces.td" include "mlir/IR/EnumAttr.td" @@ -75,6 +77,84 @@ class CIR_Op<string mnemonic, list<Trait> traits = []> : Op<CIR_Dialect, mnemonic, traits>, LLVMLoweringInfo; //===----------------------------------------------------------------------===// +// ConstantOp +//===----------------------------------------------------------------------===// + +def ConstantOp : CIR_Op<"const", + [ConstantLike, Pure, AllTypesMatch<["value", "res"]>]> { + let summary = "Defines a CIR constant"; + 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> + ``` + }]; + + // The constant operation takes an attribute as the only input. + let arguments = (ins TypedAttrInterface:$value); + + // The constant operation returns a single value of CIR_AnyType. + let results = (outs CIR_AnyType:$res); + + let assemblyFormat = "attr-dict $value"; + + let hasVerifier = 1; + + let extraClassDeclaration = [{ + bool isNullPtr() { + if (const auto ptrAttr = mlir::dyn_cast<cir::ConstPtrAttr>(getValue())) + return ptrAttr.isNullValue(); + return false; + } + }]; + + let hasFolder = 1; +} + +//===----------------------------------------------------------------------===// +// GlobalOp +//===----------------------------------------------------------------------===// + +// TODO(CIR): For starters, cir.global has only name and type. The other +// properties of a global variable will be added over time as more of ClangIR +// is upstreamed. + +def GlobalOp : CIR_Op<"global"> { + let summary = "Declare or define a global variable"; + let description = [{ + The `cir.global` operation declares or defines a named global variable. + + The backing memory for the variable is allocated statically and is + described by the type of the variable. + }]; + + let arguments = (ins SymbolNameAttr:$sym_name, TypeAttr:$sym_type, + OptionalAttr<AnyAttr>:$initial_value); + + let assemblyFormat = [{ + $sym_name + custom<GlobalOpTypeAndInitialValue>($sym_type, $initial_value) + attr-dict + }]; + + let extraClassDeclaration = [{ + bool isDeclaration() { return !getInitialValue(); } + bool hasInitializer() { return !isDeclaration(); } + }]; + + let skipDefaultBuilders = 1; + + let builders = [OpBuilder<(ins "llvm::StringRef":$sym_name, + "mlir::Type":$sym_type)>]; + + let hasVerifier = 1; +} + +//===----------------------------------------------------------------------===// // FuncOp //===----------------------------------------------------------------------===// @@ -85,14 +165,15 @@ class CIR_Op<string mnemonic, list<Trait> traits = []> : def FuncOp : CIR_Op<"func"> { let summary = "Declare or define a function"; let description = [{ - ... lots of text to be added later ... + The `cir.func` operation defines a function, similar to the `mlir::FuncOp` + built-in. }]; let arguments = (ins SymbolNameAttr:$sym_name); let skipDefaultBuilders = 1; - let builders = [OpBuilder<(ins "llvm::StringRef":$name)>]; + let builders = [OpBuilder<(ins "llvm::StringRef":$sym_name)>]; let hasCustomAssemblyFormat = 1; let hasVerifier = 1; diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h new file mode 100644 index 000000000000..5d1eb17e146d --- /dev/null +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the types in the CIR dialect. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_CIR_IR_CIRTYPES_H_ +#define MLIR_DIALECT_CIR_IR_CIRTYPES_H_ + +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/Types.h" +#include "mlir/Interfaces/DataLayoutInterfaces.h" +#include "clang/CIR/Interfaces/CIRFPTypeInterface.h" + +namespace cir { + +bool isAnyFloatingPointType(mlir::Type t); + +} // namespace cir + +//===----------------------------------------------------------------------===// +// CIR Dialect Tablegen'd Types +//===----------------------------------------------------------------------===// + +#define GET_TYPEDEF_CLASSES +#include "clang/CIR/Dialect/IR/CIROpsTypes.h.inc" + +#endif // MLIR_DIALECT_CIR_IR_CIRTYPES_H_ diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td new file mode 100644 index 000000000000..a32fb3c80111 --- /dev/null +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -0,0 +1,361 @@ +//===- CIRTypes.td - CIR dialect types ---------------------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the CIR dialect types. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_CIR_DIALECT_CIR_TYPES +#define MLIR_CIR_DIALECT_CIR_TYPES + +include "clang/CIR/Dialect/IR/CIRDialect.td" +include "clang/CIR/Interfaces/CIRFPTypeInterface.td" +include "mlir/Interfaces/DataLayoutInterfaces.td" +include "mlir/IR/AttrTypeBase.td" + +//===----------------------------------------------------------------------===// +// CIR Types +//===----------------------------------------------------------------------===// + +class CIR_Type<string name, string typeMnemonic, list<Trait> traits = [], + string baseCppClass = "::mlir::Type"> + : TypeDef<CIR_Dialect, name, traits, baseCppClass> { + let mnemonic = typeMnemonic; +} + +//===----------------------------------------------------------------------===// +// IntType +//===----------------------------------------------------------------------===// + +def CIR_IntType : CIR_Type<"Int", "int", + [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> { + let summary = "Integer type with arbitrary precision up to a fixed limit"; + let description = [{ + CIR type that represents integer types with arbitrary precision, including + standard integral types such as `int` and `long`, extended integral types + such as `__int128`, and arbitrary width types such as `_BitInt(n)`. + + Those integer types that are directly available in C/C++ standard are called + primitive integer types. Said types are: `signed char`, `short`, `int`, + `long`, `long long`, and their unsigned variations. + }]; + let parameters = (ins "unsigned":$width, "bool":$isSigned); + let hasCustomAssemblyFormat = 1; + let extraClassDeclaration = [{ + /// Return true if this is a signed integer type. + bool isSigned() const { return getIsSigned(); } + /// Return true if this is an unsigned integer type. + bool isUnsigned() const { return !getIsSigned(); } + /// Return type alias. + std::string getAlias() const { + return (isSigned() ? 's' : 'u') + std::to_string(getWidth()) + 'i'; + } + /// Return true if this is a primitive integer type (i.e. signed or unsigned + /// integer types whose bit width is 8, 16, 32, or 64). + bool isPrimitive() const { + return isValidPrimitiveIntBitwidth(getWidth()); + } + bool isSignedPrimitive() const { + return isPrimitive() && isSigned(); + } + + /// Returns a minimum bitwidth of cir::IntType + static unsigned minBitwidth() { return 1; } + /// Returns a maximum bitwidth of cir::IntType + static unsigned maxBitwidth() { return 128; } + + /// Returns true if cir::IntType that represents a primitive integer type + /// can be constructed from the provided bitwidth. + static bool isValidPrimitiveIntBitwidth(unsigned width) { + return width == 8 || width == 16 || width == 32 || width == 64; + } + }]; + let genVerifyDecl = 1; +} + +// Constraints + +// Unsigned integer type of a specific width. +class UInt<int width> + : Type<And<[ + CPred<"::mlir::isa<::cir::IntType>($_self)">, + CPred<"::mlir::cast<::cir::IntType>($_self).isUnsigned()">, + CPred<"::mlir::cast<::cir::IntType>($_self).getWidth() == " # width> + ]>, width # "-bit unsigned integer", "::cir::IntType">, + BuildableType< + "cir::IntType::get($_builder.getContext(), " + # width # ", /*isSigned=*/false)"> { + int bitwidth = width; +} + +def UInt1 : UInt<1>; +def UInt8 : UInt<8>; +def UInt16 : UInt<16>; +def UInt32 : UInt<32>; +def UInt64 : UInt<64>; + +// Signed integer type of a specific width. +class SInt<int width> + : Type<And<[ + CPred<"::mlir::isa<::cir::IntType>($_self)">, + CPred<"::mlir::cast<::cir::IntType>($_self).isSigned()">, + CPred<"::mlir::cast<::cir::IntType>($_self).getWidth() == " # width> + ]>, width # "-bit signed integer", "::cir::IntType">, + BuildableType< + "cir::IntType::get($_builder.getContext(), " + # width # ", /*isSigned=*/true)"> { + int bitwidth = width; +} + +def SInt1 : SInt<1>; +def SInt8 : SInt<8>; +def SInt16 : SInt<16>; +def SInt32 : SInt<32>; +def SInt64 : SInt<64>; + +def PrimitiveUInt + : AnyTypeOf<[UInt8, UInt16, UInt32, UInt64], "primitive unsigned int", + "::cir::IntType">; + +def PrimitiveSInt + : AnyTypeOf<[SInt8, SInt16, SInt32, SInt64], "primitive signed int", + "::cir::IntType">; + +def PrimitiveInt + : AnyTypeOf<[UInt8, UInt16, UInt32, UInt64, SInt8, SInt16, SInt32, SInt64], + "primitive int", "::cir::IntType">; + +//===----------------------------------------------------------------------===// +// FloatType +//===----------------------------------------------------------------------===// + +class CIR_FloatType<string name, string mnemonic> + : CIR_Type<name, mnemonic, + [ + DeclareTypeInterfaceMethods<DataLayoutTypeInterface>, + DeclareTypeInterfaceMethods<CIRFPTypeInterface>, + ]> {} + +def CIR_Single : CIR_FloatType<"Single", "float"> { + let summary = "CIR single-precision 32-bit float type"; + let description = [{ + A 32-bit floating-point type whose format is IEEE-754 `binary32`. It + represents the types `float`, `_Float32`, and `std::float32_t` in C and C++. + }]; +} + +def CIR_Double : CIR_FloatType<"Double", "double"> { + let summary = "CIR double-precision 64-bit float type"; + let description = [{ + A 64-bit floating-point type whose format is IEEE-754 `binary64`. It + represents the types `double', '_Float64`, `std::float64_t`, and `_Float32x` + in C and C++. This is the underlying type for `long double` on some + platforms, including Windows. + }]; +} + +def CIR_FP16 : CIR_FloatType<"FP16", "f16"> { + let summary = "CIR half-precision 16-bit float type"; + let description = [{ + A 16-bit floating-point type whose format is IEEE-754 `binary16`. It + represents the types '_Float16` and `std::float16_t` in C and C++. + }]; +} + +def CIR_BFloat16 : CIR_FloatType<"BF16", "bf16"> { + let summary = "CIR bfloat16 16-bit float type"; + let description = [{ + A 16-bit floating-point type in the bfloat16 format, which is the same as + IEEE `binary32` except that the lower 16 bits of the mantissa are missing. + It represents the type `std::bfloat16_t` in C++, also spelled `__bf16` in + some implementations. + }]; +} + +def CIR_FP80 : CIR_FloatType<"FP80", "f80"> { + let summary = "CIR x87 80-bit float type"; + let description = [{ + An 80-bit floating-point type in the x87 extended precision format. The + size and alignment of the type are both 128 bits, even though only 80 of + those bits are used. This is the underlying type for `long double` on Linux + x86 platforms, and it is available as an extension in some implementations. + }]; +} + +def CIR_FP128 : CIR_FloatType<"FP128", "f128"> { + let summary = "CIR quad-precision 128-bit float type"; + let description = [{ + A 128-bit floating-point type whose format is IEEE-754 `binary128`. It + represents the types `_Float128` and `std::float128_t` in C and C++, and the + extension `__float128` in some implementations. This is the underlying type + for `long double` on some platforms including Linux Arm. + }]; +} + +def CIR_LongDouble : CIR_FloatType<"LongDouble", "long_double"> { + let summary = "CIR float type for `long double`"; + let description = [{ + A floating-point type that represents the `long double` type in C and C++. + + The underlying floating-point format of a `long double` value depends on the + target platform and the implementation. The `underlying` parameter specifies + the CIR floating-point type that corresponds to this format. Underlying + types of IEEE 64-bit, IEEE 128-bit, x87 80-bit, and IBM's double-double + format are all in use. + }]; + + let parameters = (ins "mlir::Type":$underlying); + + let assemblyFormat = [{ + `<` $underlying `>` + }]; + + let genVerifyDecl = 1; +} + +// Constraints + +def CIR_AnyFloat: AnyTypeOf<[CIR_Single, CIR_Double, CIR_FP80, CIR_FP128, + CIR_LongDouble, CIR_FP16, CIR_BFloat16]>; +def CIR_AnyIntOrFloat: AnyTypeOf<[CIR_AnyFloat, CIR_IntType]>; + +//===----------------------------------------------------------------------===// +// PointerType +//===----------------------------------------------------------------------===// + +def CIR_PointerType : CIR_Type<"Pointer", "ptr", + [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> { + + let summary = "CIR pointer type"; + let description = [{ + The `cir.ptr` type represents C and C++ pointer types and C++ reference + types, other than pointers-to-members. The `pointee` type is the type + pointed to. + + TODO(CIR): The address space attribute is not yet implemented. + }]; + + let parameters = (ins "mlir::Type":$pointee); + + let builders = [ + TypeBuilderWithInferredContext<(ins "mlir::Type":$pointee), [{ + return $_get(pointee.getContext(), pointee); + }]>, + TypeBuilder<(ins "mlir::Type":$pointee), [{ + return $_get($_ctxt, pointee); + }]> + ]; + + let assemblyFormat = [{ + `<` $pointee `>` + }]; + + let genVerifyDecl = 1; + + let skipDefaultBuilders = 1; + + let extraClassDeclaration = [{ + bool isVoidPtr() const { + return mlir::isa<cir::VoidType>(getPointee()); + } + }]; +} + +//===----------------------------------------------------------------------===// +// FuncType +//===----------------------------------------------------------------------===// + +def CIR_FuncType : CIR_Type<"Func", "func"> { + let summary = "CIR function type"; + let description = [{ + The `!cir.func` is a function type. It consists of a single return type, a + list of parameter types and can optionally be variadic. + + Example: + + ```mlir + !cir.func<!bool ()> + !cir.func<!s32i (!s8i, !s8i)> + !cir.func<!s32i (!s32i, ...)> + ``` + }]; + + let parameters = (ins ArrayRefParameter<"mlir::Type">:$inputs, + "mlir::Type":$returnType, "bool":$varArg); + let assemblyFormat = [{ + `<` $returnType ` ` `(` custom<FuncTypeArgs>($inputs, $varArg) `>` + }]; + + let builders = [ + TypeBuilderWithInferredContext<(ins + "llvm::ArrayRef<mlir::Type>":$inputs, "mlir::Type":$returnType, + CArg<"bool", "false">:$isVarArg), [{ + return $_get(returnType.getContext(), inputs, returnType, isVarArg); + }]> + ]; + + let extraClassDeclaration = [{ + /// Returns whether the function is variadic. + bool isVarArg() const { return getVarArg(); } + + /// Returns the `i`th input operand type. Asserts if out of bounds. + mlir::Type getInput(unsigned i) const { return getInputs()[i]; } + + /// Returns the number of arguments to the function. + unsigned getNumInputs() const { return getInputs().size(); } + + /// Returns the result type of the function as an ArrayRef, enabling better + /// integration with generic MLIR utilities. + llvm::ArrayRef<mlir::Type> getReturnTypes() const; + + /// Returns whether the function is returns void. + bool isVoid() const; + + /// Returns a clone of this function type with the given argument + /// and result types. + FuncType clone(mlir::TypeRange inputs, mlir::TypeRange results) const; + }]; +} + +//===----------------------------------------------------------------------===// +// Void type +//===----------------------------------------------------------------------===// + +def CIR_VoidType : CIR_Type<"Void", "void"> { + let summary = "CIR void type"; + let description = [{ + The `!cir.void` type represents the C and C++ `void` type. + }]; + let extraClassDeclaration = [{ + std::string getAlias() const { return "void"; }; + }]; +} + +// Constraints + +// Pointer to void +def VoidPtr : Type< + And<[ + CPred<"::mlir::isa<::cir::PointerType>($_self)">, + CPred<"::mlir::isa<::cir::VoidType>(" + "::mlir::cast<::cir::PointerType>($_self).getPointee())">, + ]>, "void*">, + BuildableType< + "cir::PointerType::get($_builder.getContext()," + "cir::VoidType::get($_builder.getContext()))"> { +} + +//===----------------------------------------------------------------------===// +// Global type constraints +//===----------------------------------------------------------------------===// + +def CIR_AnyType : AnyTypeOf<[ + CIR_VoidType, CIR_IntType, CIR_AnyFloat, CIR_PointerType, CIR_FuncType +]>; + +#endif // MLIR_CIR_DIALECT_CIR_TYPES diff --git a/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt b/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt index 28ae30dab8df..1fdbc24ba6b4 100644 --- a/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt +++ b/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt @@ -14,3 +14,6 @@ mlir_tablegen(CIROpsDialect.cpp.inc -gen-dialect-defs) add_public_tablegen_target(MLIRCIROpsIncGen) add_dependencies(mlir-headers MLIRCIROpsIncGen) +mlir_tablegen(CIROpsAttributes.h.inc -gen-attrdef-decls) +mlir_tablegen(CIROpsAttributes.cpp.inc -gen-attrdef-defs) +add_public_tablegen_target(MLIRCIRAttrsEnumsGen) diff --git a/clang/include/clang/CIR/Interfaces/CIRFPTypeInterface.h b/clang/include/clang/CIR/Interfaces/CIRFPTypeInterface.h new file mode 100644 index 000000000000..40b85ef6cfb6 --- /dev/null +++ b/clang/include/clang/CIR/Interfaces/CIRFPTypeInterface.h @@ -0,0 +1,22 @@ +//===---------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// +// +// Defines the interface to generically handle CIR floating-point types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INCLUDE_CLANG_CIR_INTERFACES_CIRFPTYPEINTERFACE_H +#define LLVM_CLANG_INCLUDE_CLANG_CIR_INTERFACES_CIRFPTYPEINTERFACE_H + +#include "mlir/IR/Types.h" +#include "llvm/ADT/APFloat.h" + +/// Include the tablegen'd interface declarations. +#include "clang/CIR/Interfaces/CIRFPTypeInterface.h.inc" + +#endif // LLVM_CLANG_INCLUDE_CLANG_CIR_INTERFACES_CIRFPTYPEINTERFACE_H diff --git a/clang/include/clang/CIR/Interfaces/CIRFPTypeInterface.td b/clang/include/clang/CIR/Interfaces/CIRFPTypeInterface.td new file mode 100644 index 000000000000..973851b61444 --- /dev/null +++ b/clang/include/clang/CIR/Interfaces/CIRFPTypeInterface.td @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Defines the interface to generically handle CIR floating-point types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INCLUDE_CLANG_CIR_INTERFACES_CIRFPTYPEINTERFACE_TD +#define LLVM_CLANG_INCLUDE_CLANG_CIR_INTERFACES_CIRFPTYPEINTERFACE_TD + +include "mlir/IR/OpBase.td" + +def CIRFPTypeInterface : TypeInterface<"CIRFPTypeInterface"> { + let description = [{ + Contains helper functions to query properties about a floating-point type. + }]; + let cppNamespace = "::cir"; + + let methods = [ + InterfaceMethod<[{ + Returns the bit width of this floating-point type. + }], + /*retTy=*/"unsigned", + /*methodName=*/"getWidth", + /*args=*/(ins), + /*methodBody=*/"", + /*defaultImplementation=*/[{ + return llvm::APFloat::semanticsSizeInBits($_type.getFloatSemantics()); + }] + >, + InterfaceMethod<[{ + Return the mantissa width. + }], + /*retTy=*/"unsigned", + /*methodName=*/"getFPMantissaWidth", + /*args=*/(ins), + /*methodBody=*/"", + /*defaultImplementation=*/[{ + return llvm::APFloat::semanticsPrecision($_type.getFloatSemantics()); + }] + >, + InterfaceMethod<[{ + Return the float semantics of this floating-point type. + }], + /*retTy=*/"const llvm::fltSemantics &", + /*methodName=*/"getFloatSemantics" + >, + ]; +} + +#endif // LLVM_CLANG_INCLUDE_CLANG_CIR_INTERFACES_CIRFPTYPEINTERFACE_TD diff --git a/clang/include/clang/CIR/Interfaces/CMakeLists.txt b/clang/include/clang/CIR/Interfaces/CMakeLists.txt new file mode 100644 index 000000000000..1c90b6b5a23c --- /dev/null +++ b/clang/include/clang/CIR/Interfaces/CMakeLists.txt @@ -0,0 +1,14 @@ +# This replicates part of the add_mlir_interface cmake function from MLIR that +# cannot be used here. This happens because it expects to be run inside MLIR +# directory which is not the case for CIR (and also FIR, both have similar +# workarounds). + +function(add_clang_mlir_type_interface interface) + set(LLVM_TARGET_DEFINITIONS ${interface}.td) + mlir_tablegen(${interface}.h.inc -gen-type-interface-decls) + mlir_tablegen(${interface}.cpp.inc -gen-type-interface-defs) + add_public_tablegen_target(MLIR${interface}IncGen) + add_dependencies(mlir-generic-headers MLIR${interface}IncGen) +endfunction() + +add_clang_mlir_type_interface(CIRFPTypeInterface) diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index 9177d56718ee..c23d037e725b 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -297,8 +297,11 @@ private: /// Object that stores strings read from configuration file. llvm::StringSaver Saver; - /// Arguments originated from configuration file. - std::unique_ptr<llvm::opt::InputArgList> CfgOptions; + /// Arguments originated from configuration file (head part). + std::unique_ptr<llvm::opt::InputArgList> CfgOptionsHead; + + /// Arguments originated from configuration file (tail part). + std::unique_ptr<llvm::opt::InputArgList> CfgOptionsTail; /// Arguments originated from command line. std::unique_ptr<llvm::opt::InputArgList> CLOptions; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index a89a4e8f8ec9..523761f5e0d8 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -240,7 +240,8 @@ def m_riscv_Features_Group : OptionGroup<"<riscv features group>">, def m_ve_Features_Group : OptionGroup<"<ve features group>">, Group<m_Group>, DocName<"VE">; def m_loongarch_Features_Group : OptionGroup<"<loongarch features group>">, - Group<m_Group>, DocName<"LoongArch">; + Group<m_Group>, DocName<"LoongArch">, + Visibility<[ClangOption, CLOption, FlangOption]>; def m_libc_Group : OptionGroup<"<m libc group>">, Group<m_mips_Features_Group>, Flags<[HelpHidden]>; @@ -1055,11 +1056,11 @@ def z : Separate<["-"], "z">, Flags<[LinkerInput]>, def offload_link : Flag<["--"], "offload-link">, Group<Link_Group>, HelpText<"Use the new offloading linker to perform the link job.">; def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>, - Visibility<[ClangOption, CLOption, FlangOption, DXCOption]>, + Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">, Group<Link_Group>; def Xoffload_linker : JoinedAndSeparate<["-"], "Xoffload-linker">, - Visibility<[ClangOption, CLOption, FlangOption, DXCOption]>, + Visibility<[ClangOption, FlangOption]>, HelpText<"Pass <arg> to the offload linkers or the ones identified by -<triple>">, MetaVarName<"<triple> <arg>">, Group<Link_Group>; def Xpreprocessor : Separate<["-"], "Xpreprocessor">, Group<Preprocessor_Group>, @@ -1175,7 +1176,7 @@ def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">; def config : Joined<["--"], "config=">, Flags<[NoXarchOption]>, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, MetaVarName<"<file>">, HelpText<"Specify configuration file">; -def : Separate<["--"], "config">, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, Alias<config>; +def : Separate<["--"], "config">, Visibility<[ClangOption, FlangOption]>, Alias<config>; def no_default_config : Flag<["--"], "no-default-config">, Flags<[NoXarchOption]>, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, HelpText<"Disable loading default configuration files">; @@ -1492,6 +1493,8 @@ def libomptarget_amdgcn_bc_path_EQ : Joined<["--"], "libomptarget-amdgcn-bc-path HelpText<"Path to libomptarget-amdgcn bitcode library">, Alias<libomptarget_amdgpu_bc_path_EQ>; def libomptarget_nvptx_bc_path_EQ : Joined<["--"], "libomptarget-nvptx-bc-path=">, Group<i_Group>, HelpText<"Path to libomptarget-nvptx bitcode library">; +def libomptarget_spirv_bc_path_EQ : Joined<["--"], "libomptarget-spirv-bc-path=">, Group<i_Group>, + HelpText<"Path to libomptarget-spirv bitcode library">; def dD : Flag<["-"], "dD">, Group<d_Group>, Visibility<[ClangOption, CC1Option]>, HelpText<"Print macro definitions in -E mode in addition to normal output">; def dI : Flag<["-"], "dI">, Group<d_Group>, Visibility<[ClangOption, CC1Option]>, @@ -2015,10 +2018,10 @@ argument are escaped with backslashes. This format differs from the format of the equivalent section produced by GCC with the -frecord-gcc-switches flag. This option is currently only supported on ELF targets.}]>, Group<f_Group>, - Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>; + Visibility<[ClangOption, FlangOption]>; def fno_record_command_line : Flag<["-"], "fno-record-command-line">, Group<f_Group>, - Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>; + Visibility<[ClangOption, FlangOption]>; def : Flag<["-"], "frecord-gcc-switches">, Alias<frecord_command_line>; def : Flag<["-"], "fno-record-gcc-switches">, Alias<fno_record_command_line>; def fcommon : Flag<["-"], "fcommon">, Group<f_Group>, @@ -2554,6 +2557,21 @@ def fno_sanitize_trap : Flag<["-"], "fno-sanitize-trap">, Group<f_clang_Group>, Alias<fno_sanitize_trap_EQ>, AliasArgs<["all"]>, Visibility<[ClangOption, CLOption]>, HelpText<"Disable trapping for all sanitizers">; +def fsanitize_merge_handlers_EQ + : CommaJoined<["-"], "fsanitize-merge=">, + Group<f_clang_Group>, + HelpText<"Allow compiler to merge handlers for specified sanitizers">; +def fno_sanitize_merge_handlers_EQ + : CommaJoined<["-"], "fno-sanitize-merge=">, + Group<f_clang_Group>, + HelpText<"Do not allow compiler to merge handlers for specified sanitizers">; +def fsanitize_merge_handlers : Flag<["-"], "fsanitize-merge">, Group<f_clang_Group>, + Alias<fsanitize_merge_handlers_EQ>, AliasArgs<["all"]>, + HelpText<"Allow compiler to merge handlers for all sanitizers">; +def fno_sanitize_merge_handlers : Flag<["-"], "fno-sanitize-merge">, Group<f_clang_Group>, + Alias<fno_sanitize_merge_handlers_EQ>, AliasArgs<["all"]>, + Visibility<[ClangOption, CLOption]>, + HelpText<"Do not allow compiler to merge handlers for any sanitizers">; def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">, Group<f_clang_Group>, Alias<fsanitize_trap_EQ>, AliasArgs<["undefined"]>; @@ -3194,11 +3212,14 @@ defm skip_odr_check_in_gmf : BoolOption<"f", "skip-odr-check-in-gmf", "Perform ODR checks for decls in the global module fragment.">>, Group<f_Group>; -def modules_reduced_bmi : Flag<["-"], "fexperimental-modules-reduced-bmi">, +def modules_reduced_bmi : Flag<["-"], "fmodules-reduced-bmi">, Group<f_Group>, Visibility<[ClangOption, CC1Option]>, HelpText<"Generate the reduced BMI">, MarshallingInfoFlag<FrontendOpts<"GenReducedBMI">>; +def experimental_modules_reduced_bmi : Flag<["-"], "fexperimental-modules-reduced-bmi">, + Group<f_Group>, Visibility<[ClangOption, CC1Option]>, Alias<modules_reduced_bmi>; + def fmodules_embed_all_files : Joined<["-"], "fmodules-embed-all-files">, Visibility<[ClangOption, CC1Option, CLOption]>, HelpText<"Embed the contents of all files read by this compilation into " @@ -3459,6 +3480,9 @@ defm diagnostics_show_line_numbers : BoolFOption<"diagnostics-show-line-numbers" NegFlag<SetFalse, [], [ClangOption, CC1Option], "Show line numbers in diagnostic code snippets">, PosFlag<SetTrue>>; +def fno_realloc_lhs : Flag<["-"], "fno-realloc-lhs">, Group<f_Group>, + HelpText<"An allocatable left-hand side of an intrinsic assignment is assumed to be allocated and match the shape/type of the right-hand side">, + Visibility<[FlangOption, FC1Option]>; def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group<f_Group>, HelpText<"Disable the use of stack protectors">; def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>, @@ -4292,6 +4316,9 @@ defm stack_size_section : BoolFOption<"stack-size-section", PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit section containing metadata on function stack sizes">, NegFlag<SetFalse>>; +def frealloc_lhs : Flag<["-"], "frealloc-lhs">, Group<f_Group>, + Visibility<[FlangOption, FC1Option]>, + HelpText<"If an allocatable left-hand side of an intrinsic assignment is unallocated or its shape/type does not match the right-hand side, then it is automatically (re)allocated">; def fstack_usage : Flag<["-"], "fstack-usage">, Group<f_Group>, HelpText<"Emit .su file containing information on function stack sizes">; def stack_usage_file : Separate<["-"], "stack-usage-file">, @@ -5644,7 +5671,7 @@ def gpulibc : Flag<["-"], "gpulibc">, Visibility<[ClangOption, CC1Option, FlangO HelpText<"Link the LLVM C Library for GPUs">; def nogpulibc : Flag<["-"], "nogpulibc">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>; def nodefaultlibs : Flag<["-"], "nodefaultlibs">, - Visibility<[ClangOption, FlangOption, CLOption, DXCOption]>; + Visibility<[ClangOption, FlangOption]>; def nodriverkitlib : Flag<["-"], "nodriverkitlib">; def nofixprebinding : Flag<["-"], "nofixprebinding">; def nolibc : Flag<["-"], "nolibc">; @@ -5666,10 +5693,10 @@ def nostdincxx : Flag<["-"], "nostdinc++">, Visibility<[ClangOption, CC1Option]> HelpText<"Disable standard #include directories for the C++ standard library">, MarshallingInfoNegativeFlag<HeaderSearchOpts<"UseStandardCXXIncludes">>; def nostdlib : Flag<["-"], "nostdlib">, - Visibility<[ClangOption, CLOption, FlangOption, DXCOption]>, + Visibility<[ClangOption, FlangOption]>, Group<Link_Group>; def stdlib : Flag<["-"], "stdlib">, - Visibility<[ClangOption, CLOption, FlangOption, DXCOption]>, + Visibility<[ClangOption, FlangOption]>, Group<Link_Group>; def nostdlibxx : Flag<["-"], "nostdlib++">; def object : Flag<["-"], "object">; @@ -5783,7 +5810,7 @@ def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[NoXarchOption]>, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, Alias<resource_dir>; def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>, Group<Link_Group>, - Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>; + Visibility<[ClangOption, FlangOption]>; def rtlib_EQ : Joined<["-", "--"], "rtlib=">, Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Compiler runtime library to use">; def frtlib_add_rpath: Flag<["-"], "frtlib-add-rpath">, Flags<[NoArgumentUnused]>, @@ -5847,7 +5874,7 @@ def segs__read__write__addr : Separate<["-"], "segs_read_write_addr">; def segs__read__ : Joined<["-"], "segs_read_">; def shared_libgcc : Flag<["-"], "shared-libgcc">; def shared : Flag<["-", "--"], "shared">, Group<Link_Group>, - Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>; + Visibility<[ClangOption, FlangOption]>; def single__module : Flag<["-"], "single_module">; def specs_EQ : Joined<["-", "--"], "specs=">, Group<Link_Group>; def specs : Separate<["-", "--"], "specs">, Flags<[Unsupported]>; @@ -5857,7 +5884,7 @@ def start_no_unused_arguments : Flag<["--"], "start-no-unused-arguments">, def static_libgcc : Flag<["-"], "static-libgcc">; def static_libstdcxx : Flag<["-"], "static-libstdc++">; def static : Flag<["-", "--"], "static">, Group<Link_Group>, - Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, + Visibility<[ClangOption, FlangOption]>, Flags<[NoArgumentUnused]>; def std_default_EQ : Joined<["-"], "std-default=">; def std_EQ : Joined<["-", "--"], "std=">, @@ -6199,6 +6226,10 @@ def mv71t : Flag<["-"], "mv71t">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>, AliasArgs<["hexagonv71t"]>; def mv73 : Flag<["-"], "mv73">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>, AliasArgs<["hexagonv73"]>; +def mv75 : Flag<["-"], "mv75">, Group<m_hexagon_Features_Group>, + Alias<mcpu_EQ>, AliasArgs<["hexagonv75"]>; +def mv79 : Flag<["-"], "mv79">, Group<m_hexagon_Features_Group>, + Alias<mcpu_EQ>, AliasArgs<["hexagonv79"]>; def mhexagon_hvx : Flag<["-"], "mhvx">, Group<m_hexagon_Features_HVX_Group>, HelpText<"Enable Hexagon Vector eXtensions">; def mhexagon_hvx_EQ : Joined<["-"], "mhvx=">, @@ -6771,7 +6802,6 @@ defm real_4_real_8 : BooleanFFlag<"real-4-real-8">, Group<gfortran_Group>; defm real_8_real_10 : BooleanFFlag<"real-8-real-10">, Group<gfortran_Group>; defm real_8_real_16 : BooleanFFlag<"real-8-real-16">, Group<gfortran_Group>; defm real_8_real_4 : BooleanFFlag<"real-8-real-4">, Group<gfortran_Group>; -defm realloc_lhs : BooleanFFlag<"realloc-lhs">, Group<gfortran_Group>; defm recursive : BooleanFFlag<"recursive">, Group<gfortran_Group>; defm repack_arrays : BooleanFFlag<"repack-arrays">, Group<gfortran_Group>; defm second_underscore : BooleanFFlag<"second-underscore">, Group<gfortran_Group>; @@ -6836,10 +6866,6 @@ def flang_deprecated_no_hlfir : Flag<["-"], "flang-deprecated-no-hlfir">, Flags<[HelpHidden]>, Visibility<[FlangOption, FC1Option]>, HelpText<"Do not use HLFIR lowering (deprecated)">; -def flang_experimental_integer_overflow : Flag<["-"], "flang-experimental-integer-overflow">, - Flags<[HelpHidden]>, Visibility<[FlangOption, FC1Option]>, - HelpText<"Add nsw flag to internal operations such as do-variable increment (experimental)">; - //===----------------------------------------------------------------------===// // FLangOption + CoreOption + NoXarchOption //===----------------------------------------------------------------------===// @@ -6908,6 +6934,7 @@ defm underscoring : OptInFC1FFlag<"underscoring", "Appends one trailing undersco defm ppc_native_vec_elem_order: BoolOptionWithoutMarshalling<"f", "ppc-native-vector-element-order", PosFlag<SetTrue, [], [ClangOption], "Specifies PowerPC native vector element order (default)">, NegFlag<SetFalse, [], [ClangOption], "Specifies PowerPC non-native vector element order">>; +defm unsigned : OptInFC1FFlag<"unsigned", "Enables UNSIGNED type">; def fno_automatic : Flag<["-"], "fno-automatic">, Group<f_Group>, HelpText<"Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE">; diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h index 0c6f3869549e..3b275092bbbe 100644 --- a/clang/include/clang/Driver/SanitizerArgs.h +++ b/clang/include/clang/Driver/SanitizerArgs.h @@ -25,6 +25,7 @@ class SanitizerArgs { SanitizerSet Sanitizers; SanitizerSet RecoverableSanitizers; SanitizerSet TrapSanitizers; + SanitizerSet MergeHandlers; std::vector<std::string> UserIgnorelistFiles; std::vector<std::string> SystemIgnorelistFiles; @@ -87,6 +88,7 @@ public: bool needsHwasanAliasesRt() const { return needsHwasanRt() && HwasanUseAliases; } + bool needsTysanRt() const { return Sanitizers.has(SanitizerKind::Type); } bool needsTsanRt() const { return Sanitizers.has(SanitizerKind::Thread); } bool needsMsanRt() const { return Sanitizers.has(SanitizerKind::Memory); } bool needsFuzzer() const { return Sanitizers.has(SanitizerKind::Fuzzer); } @@ -97,6 +99,7 @@ public: } bool needsFuzzerInterceptors() const; bool needsUbsanRt() const; + bool needsUbsanCXXRt() const; bool requiresMinimalRuntime() const { return MinimalRuntime; } bool needsDfsanRt() const { return Sanitizers.has(SanitizerKind::DataFlow); } bool needsSafeStackRt() const { return SafeStackRuntime; } diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 6383934afa2c..9b7a633e0a14 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -988,6 +988,10 @@ struct FormatStyle { /// \version 3.7 bool AllowShortLoopsOnASingleLine; + /// If ``true``, ``namespace a { class b; }`` can be put on a single line. + /// \version 20 + bool AllowShortNamespacesOnASingleLine; + /// Different ways to break after the function definition return type. /// This option is **deprecated** and is retained for backwards compatibility. enum DefinitionReturnTypeBreakingStyle : int8_t { @@ -5099,6 +5103,15 @@ struct FormatStyle { /// \version 3.7 UseTabStyle UseTab; + /// A vector of non-keyword identifiers that should be interpreted as variable + /// template names. + /// + /// A ``)`` after a variable template instantiation is **not** annotated as + /// the closing parenthesis of C-style cast operator. + /// + /// \version 20 + std::vector<std::string> VariableTemplates; + /// For Verilog, put each port on its own line in module instantiations. /// \code /// true: @@ -5130,6 +5143,39 @@ struct FormatStyle { /// \version 11 std::vector<std::string> WhitespaceSensitiveMacros; + /// Different styles for wrapping namespace body with empty lines. + enum WrapNamespaceBodyWithEmptyLinesStyle : int8_t { + /// Remove all empty lines at the beginning and the end of namespace body. + /// \code + /// namespace N1 { + /// namespace N2 + /// function(); + /// } + /// } + /// \endcode + WNBWELS_Never, + /// Always have at least one empty line at the beginning and the end of + /// namespace body except that the number of empty lines between consecutive + /// nested namespace definitions is not increased. + /// \code + /// namespace N1 { + /// namespace N2 { + /// + /// function(); + /// + /// } + /// } + /// \endcode + WNBWELS_Always, + /// Keep existing newlines at the beginning and the end of namespace body. + /// ``MaxEmptyLinesToKeep`` still applies. + WNBWELS_Leave + }; + + /// Wrap namespace body with empty lines. + /// \version 20 + WrapNamespaceBodyWithEmptyLinesStyle WrapNamespaceBodyWithEmptyLines; + bool operator==(const FormatStyle &R) const { return AccessModifierOffset == R.AccessModifierOffset && AlignAfterOpenBracket == R.AlignAfterOpenBracket && @@ -5168,6 +5214,8 @@ struct FormatStyle { R.AllowShortIfStatementsOnASingleLine && AllowShortLambdasOnASingleLine == R.AllowShortLambdasOnASingleLine && AllowShortLoopsOnASingleLine == R.AllowShortLoopsOnASingleLine && + AllowShortNamespacesOnASingleLine == + R.AllowShortNamespacesOnASingleLine && AlwaysBreakBeforeMultilineStrings == R.AlwaysBreakBeforeMultilineStrings && AttributeMacros == R.AttributeMacros && @@ -5308,10 +5356,11 @@ struct FormatStyle { TableGenBreakInsideDAGArg == R.TableGenBreakInsideDAGArg && TabWidth == R.TabWidth && TemplateNames == R.TemplateNames && TypeNames == R.TypeNames && TypenameMacros == R.TypenameMacros && - UseTab == R.UseTab && + UseTab == R.UseTab && VariableTemplates == R.VariableTemplates && VerilogBreakBetweenInstancePorts == R.VerilogBreakBetweenInstancePorts && - WhitespaceSensitiveMacros == R.WhitespaceSensitiveMacros; + WhitespaceSensitiveMacros == R.WhitespaceSensitiveMacros && + WrapNamespaceBodyWithEmptyLines == R.WrapNamespaceBodyWithEmptyLines; } std::optional<FormatStyle> GetLanguageStyle(LanguageKind Language) const; diff --git a/clang/include/clang/Frontend/Utils.h b/clang/include/clang/Frontend/Utils.h index 604e42067a3f..8ed17179c982 100644 --- a/clang/include/clang/Frontend/Utils.h +++ b/clang/include/clang/Frontend/Utils.h @@ -120,6 +120,7 @@ protected: private: void outputDependencyFile(DiagnosticsEngine &Diags); + llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; std::string OutputFile; std::vector<std::string> Targets; bool IncludeSystemHeaders; diff --git a/clang/include/clang/Lex/PreprocessingRecord.h b/clang/include/clang/Lex/PreprocessingRecord.h index 437d8e4cc174..7886aef7f0c7 100644 --- a/clang/include/clang/Lex/PreprocessingRecord.h +++ b/clang/include/clang/Lex/PreprocessingRecord.h @@ -180,13 +180,13 @@ class Token; } /// True if it is a builtin macro. - bool isBuiltinMacro() const { return NameOrDef.is<IdentifierInfo *>(); } + bool isBuiltinMacro() const { return isa<IdentifierInfo *>(NameOrDef); } /// The name of the macro being expanded. const IdentifierInfo *getName() const { if (MacroDefinitionRecord *Def = getDefinition()) return Def->getName(); - return NameOrDef.get<IdentifierInfo *>(); + return cast<IdentifierInfo *>(NameOrDef); } /// The definition of the macro being expanded. May return null if diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 3312d4ed1d79..3d223c345ea1 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -859,7 +859,7 @@ private: auto *Info = State.dyn_cast<ModuleMacroInfo*>(); if (!Info) { Info = new (PP.getPreprocessorAllocator()) - ModuleMacroInfo(State.get<MacroDirective *>()); + ModuleMacroInfo(cast<MacroDirective *>(State)); State = Info; } @@ -892,7 +892,7 @@ private: MacroDirective *getLatest() const { if (auto *Info = State.dyn_cast<ModuleMacroInfo*>()) return Info->MD; - return State.get<MacroDirective*>(); + return cast<MacroDirective *>(State); } void setLatest(MacroDirective *MD) { @@ -945,7 +945,7 @@ private: if (Overrides.empty()) return; Info = new (PP.getPreprocessorAllocator()) - ModuleMacroInfo(State.get<MacroDirective *>()); + ModuleMacroInfo(cast<MacroDirective *>(State)); State = Info; } Info->OverriddenMacros.clear(); diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index d3838a4cc841..e99d2cf2eaa4 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3706,10 +3706,14 @@ private: OpenACCDirectiveKind DirKind; SourceLocation StartLoc; SourceLocation DirLoc; + SourceLocation LParenLoc; + SourceLocation RParenLoc; SourceLocation EndLoc; + SourceLocation MiscLoc; + SmallVector<Expr *> Exprs; SmallVector<OpenACCClause *> Clauses; - // TODO OpenACC: As we implement support for the Atomic, Routine, Cache, and - // Wait constructs, we likely want to put that information in here as well. + // TODO OpenACC: As we implement support for the Atomic, Routine, and Cache + // constructs, we likely want to put that information in here as well. }; struct OpenACCWaitParseInfo { @@ -3717,6 +3721,13 @@ private: Expr *DevNumExpr = nullptr; SourceLocation QueuesLoc; SmallVector<Expr *> QueueIdExprs; + + SmallVector<Expr *> getAllExprs() { + SmallVector<Expr *> Out; + Out.push_back(DevNumExpr); + Out.insert(Out.end(), QueueIdExprs.begin(), QueueIdExprs.end()); + return Out; + } }; /// Represents the 'error' state of parsing an OpenACC Clause, and stores diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h index 3d1906d86992..0c92c52854c9 100644 --- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h @@ -97,6 +97,12 @@ public: bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override; + bool LoadExternalSpecializations(const Decl *D, bool OnlyPartial) override; + + bool + LoadExternalSpecializations(const Decl *D, + ArrayRef<TemplateArgument> TemplateArgs) override; + /// Ensures that the table of all visible declarations inside this /// context is up to date. void completeVisibleDeclsMap(const DeclContext *DC) override; diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h index 22cbd0d90ee4..4fa5fbdb5a7f 100644 --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -392,19 +392,17 @@ public: } bool isArgExpr(unsigned Arg) const { - return Arg < NumArgs && getArg(Arg).is<Expr*>(); + return Arg < NumArgs && isa<Expr *>(getArg(Arg)); } - Expr *getArgAsExpr(unsigned Arg) const { - return getArg(Arg).get<Expr*>(); - } + Expr *getArgAsExpr(unsigned Arg) const { return cast<Expr *>(getArg(Arg)); } bool isArgIdent(unsigned Arg) const { - return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>(); + return Arg < NumArgs && isa<IdentifierLoc *>(getArg(Arg)); } IdentifierLoc *getArgAsIdent(unsigned Arg) const { - return getArg(Arg).get<IdentifierLoc*>(); + return cast<IdentifierLoc *>(getArg(Arg)); } const AvailabilityChange &getAvailabilityIntroduced() const { diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b8684d11460e..5ee7ea48cc98 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5314,7 +5314,7 @@ public: /// is complete. void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl, SourceLocation EqualLoc, - Expr *Init); + ExprResult Init); /// Handle a C++ member initializer using parentheses syntax. MemInitResult @@ -10659,6 +10659,11 @@ public: SourceLocation EndLoc); void ActOnForEachDeclStmt(DeclGroupPtrTy Decl); + /// DiagnoseDiscardedExprMarkedNodiscard - Given an expression that is + /// semantically a discarded-value expression, diagnose if any [[nodiscard]] + /// value has been discarded. + void DiagnoseDiscardedExprMarkedNodiscard(const Expr *E); + /// DiagnoseUnusedExprResult - If the statement passed in is an expression /// whose result is unused, warn. void DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID); diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h index 4b1abccb7741..5c599a70532f 100644 --- a/clang/include/clang/Sema/SemaConcept.h +++ b/clang/include/clang/Sema/SemaConcept.h @@ -135,31 +135,20 @@ struct NormalizedConstraint { return *this; } - bool isAtomic() const { return Constraint.is<AtomicConstraint *>(); } + bool isAtomic() const { return llvm::isa<AtomicConstraint *>(Constraint); } bool isFoldExpanded() const { - return Constraint.is<FoldExpandedConstraint *>(); + return llvm::isa<FoldExpandedConstraint *>(Constraint); } - bool isCompound() const { return Constraint.is<CompoundConstraint>(); } + bool isCompound() const { return llvm::isa<CompoundConstraint>(Constraint); } - CompoundConstraintKind getCompoundKind() const { - assert(isCompound() && "getCompoundKind on a non-compound constraint.."); - return Constraint.get<CompoundConstraint>().getInt(); - } + CompoundConstraintKind getCompoundKind() const; NormalizedConstraint &getLHS() const; NormalizedConstraint &getRHS() const; - AtomicConstraint *getAtomicConstraint() const { - assert(isAtomic() && - "getAtomicConstraint called on non-atomic constraint."); - return Constraint.get<AtomicConstraint *>(); - } + AtomicConstraint *getAtomicConstraint() const; - FoldExpandedConstraint *getFoldExpandedConstraint() const { - assert(isFoldExpanded() && - "getFoldExpandedConstraint called on non-fold-expanded constraint."); - return Constraint.get<FoldExpandedConstraint *>(); - } + FoldExpandedConstraint *getFoldExpandedConstraint() const; private: static std::optional<NormalizedConstraint> @@ -210,17 +199,17 @@ bool subsumes(const NormalForm &PDNF, const NormalForm &QCNF, bool Found = false; for (NormalFormConstraint Pia : Pi) { for (NormalFormConstraint Qjb : Qj) { - if (Pia.is<FoldExpandedConstraint *>() && - Qjb.is<FoldExpandedConstraint *>()) { - if (Pia.get<FoldExpandedConstraint *>()->subsumes( - *Qjb.get<FoldExpandedConstraint *>(), E)) { + if (isa<FoldExpandedConstraint *>(Pia) && + isa<FoldExpandedConstraint *>(Qjb)) { + if (cast<FoldExpandedConstraint *>(Pia)->subsumes( + *cast<FoldExpandedConstraint *>(Qjb), E)) { Found = true; break; } - } else if (Pia.is<AtomicConstraint *>() && - Qjb.is<AtomicConstraint *>()) { - if (E(*Pia.get<AtomicConstraint *>(), - *Qjb.get<AtomicConstraint *>())) { + } else if (isa<AtomicConstraint *>(Pia) && + isa<AtomicConstraint *>(Qjb)) { + if (E(*cast<AtomicConstraint *>(Pia), + *cast<AtomicConstraint *>(Qjb))) { Found = true; break; } diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index ee685d95c961..f4cd11f423a8 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -119,6 +119,7 @@ public: void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL); void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL); void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL); + void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL); void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL); void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL); void handleShaderAttr(Decl *D, const ParsedAttr &AL); diff --git a/clang/include/clang/Sema/SemaInternal.h b/clang/include/clang/Sema/SemaInternal.h index 41d05b2bfb07..27cda7198972 100644 --- a/clang/include/clang/Sema/SemaInternal.h +++ b/clang/include/clang/Sema/SemaInternal.h @@ -75,7 +75,7 @@ getDepthAndIndex(UnexpandedParameterPack UPP) { if (const auto *TTP = UPP.first.dyn_cast<const TemplateTypeParmType *>()) return std::make_pair(TTP->getDepth(), TTP->getIndex()); - return getDepthAndIndex(UPP.first.get<NamedDecl *>()); + return getDepthAndIndex(cast<NamedDecl *>(UPP.first)); } class TypoCorrectionConsumer : public VisibleDeclConsumer { diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index d720cf3c74d8..addc33bf3c76 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -164,9 +164,14 @@ public: } /// If there is a current 'active' loop construct with a 'gang' clause on a - /// 'kernel' construct, this will have the source location for it. This - /// permits us to implement the restriction of no further 'gang' clauses. - SourceLocation LoopGangClauseOnKernelLoc; + /// 'kernel' construct, this will have the source location for it, and the + /// 'kernel kind'. This permits us to implement the restriction of no further + /// 'gang' clauses. + struct LoopGangOnKernelTy { + SourceLocation Loc; + OpenACCDirectiveKind DirKind = OpenACCDirectiveKind::Invalid; + } LoopGangClauseOnKernel; + /// If there is a current 'active' loop construct with a 'worker' clause on it /// (on any sort of construct), this has the source location for it. This /// permits us to implement the restriction of no further 'gang' or 'worker' @@ -291,13 +296,15 @@ public: assert((ClauseKind == OpenACCClauseKind::NumGangs || ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::Async || + ClauseKind == OpenACCClauseKind::DeviceNum || ClauseKind == OpenACCClauseKind::Tile || ClauseKind == OpenACCClauseKind::Worker || ClauseKind == OpenACCClauseKind::Vector || ClauseKind == OpenACCClauseKind::VectorLength) && "Parsed clause kind does not have a int exprs"); - // 'async' and 'wait' have an optional IntExpr, so be tolerant of that. + // 'async', 'worker', 'vector', and 'wait' have an optional IntExpr, so be + // tolerant of that. if ((ClauseKind == OpenACCClauseKind::Async || ClauseKind == OpenACCClauseKind::Worker || ClauseKind == OpenACCClauseKind::Vector || @@ -341,6 +348,7 @@ public: assert((ClauseKind == OpenACCClauseKind::NumGangs || ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::Async || + ClauseKind == OpenACCClauseKind::DeviceNum || ClauseKind == OpenACCClauseKind::Tile || ClauseKind == OpenACCClauseKind::Gang || ClauseKind == OpenACCClauseKind::Worker || @@ -394,6 +402,9 @@ public: ClauseKind == OpenACCClauseKind::PCreate || ClauseKind == OpenACCClauseKind::PresentOrCreate || ClauseKind == OpenACCClauseKind::Attach || + ClauseKind == OpenACCClauseKind::Delete || + ClauseKind == OpenACCClauseKind::UseDevice || + ClauseKind == OpenACCClauseKind::Detach || ClauseKind == OpenACCClauseKind::DevicePtr || ClauseKind == OpenACCClauseKind::Reduction || ClauseKind == OpenACCClauseKind::FirstPrivate) && @@ -474,6 +485,7 @@ public: assert((ClauseKind == OpenACCClauseKind::NumGangs || ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::Async || + ClauseKind == OpenACCClauseKind::DeviceNum || ClauseKind == OpenACCClauseKind::Tile || ClauseKind == OpenACCClauseKind::Worker || ClauseKind == OpenACCClauseKind::Vector || @@ -485,6 +497,7 @@ public: assert((ClauseKind == OpenACCClauseKind::NumGangs || ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::Async || + ClauseKind == OpenACCClauseKind::DeviceNum || ClauseKind == OpenACCClauseKind::Tile || ClauseKind == OpenACCClauseKind::Worker || ClauseKind == OpenACCClauseKind::Vector || @@ -530,6 +543,9 @@ public: ClauseKind == OpenACCClauseKind::PCreate || ClauseKind == OpenACCClauseKind::PresentOrCreate || ClauseKind == OpenACCClauseKind::Attach || + ClauseKind == OpenACCClauseKind::Delete || + ClauseKind == OpenACCClauseKind::UseDevice || + ClauseKind == OpenACCClauseKind::Detach || ClauseKind == OpenACCClauseKind::DevicePtr || ClauseKind == OpenACCClauseKind::FirstPrivate) && "Parsed clause kind does not have a var-list"); @@ -566,6 +582,9 @@ public: ClauseKind == OpenACCClauseKind::PCreate || ClauseKind == OpenACCClauseKind::PresentOrCreate || ClauseKind == OpenACCClauseKind::Attach || + ClauseKind == OpenACCClauseKind::Delete || + ClauseKind == OpenACCClauseKind::UseDevice || + ClauseKind == OpenACCClauseKind::Detach || ClauseKind == OpenACCClauseKind::DevicePtr || ClauseKind == OpenACCClauseKind::FirstPrivate) && "Parsed clause kind does not have a var-list"); @@ -648,7 +667,8 @@ public: /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES /// happen before any associated declarations or statements have been parsed. /// This function is only called when we are parsing a 'statement' context. - bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc); + bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, + ArrayRef<const OpenACCClause *> Clauses); /// Called after the directive, including its clauses, have been parsed and /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES @@ -664,12 +684,18 @@ public: /// Called after the directive has been completely parsed, including the /// declaration group or associated statement. - StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, - SourceLocation StartLoc, - SourceLocation DirLoc, - SourceLocation EndLoc, - ArrayRef<OpenACCClause *> Clauses, - StmtResult AssocStmt); + /// LParenLoc: Location of the left paren, if it exists (not on all + /// constructs). + /// MiscLoc: First misc location, if necessary (not all constructs). + /// Exprs: List of expressions on the construct itself, if necessary (not all + /// constructs). + /// RParenLoc: Location of the right paren, if it exists (not on all + /// constructs). + StmtResult ActOnEndStmtDirective( + OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, + SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs, + SourceLocation RParenLoc, SourceLocation EndLoc, + ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt); /// Called after the directive has been completely parsed, including the /// declaration group or associated statement. @@ -705,12 +731,15 @@ public: ExprResult CheckTileSizeExpr(Expr *SizeExpr); // Check a single expression on a gang clause. - ExprResult CheckGangExpr(OpenACCGangKind GK, Expr *E); + ExprResult CheckGangExpr(ArrayRef<const OpenACCClause *> ExistingClauses, + OpenACCDirectiveKind DK, OpenACCGangKind GK, + Expr *E); // Does the checking for a 'gang' clause that needs to be done in dependent // and not dependent cases. OpenACCClause * - CheckGangClause(ArrayRef<const OpenACCClause *> ExistingClauses, + CheckGangClause(OpenACCDirectiveKind DirKind, + ArrayRef<const OpenACCClause *> ExistingClauses, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef<OpenACCGangKind> GangKinds, ArrayRef<Expr *> IntExprs, SourceLocation EndLoc); @@ -771,7 +800,7 @@ public: SemaOpenACC &SemaRef; ComputeConstructInfo OldActiveComputeConstructInfo; OpenACCDirectiveKind DirKind; - SourceLocation OldLoopGangClauseOnKernelLoc; + LoopGangOnKernelTy OldLoopGangClauseOnKernel; SourceLocation OldLoopWorkerClauseLoc; SourceLocation OldLoopVectorClauseLoc; LoopWithoutSeqCheckingInfo OldLoopWithoutSeqInfo; diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index 6872d04cc4df..9800f75f676a 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -486,10 +486,10 @@ enum class TemplateSubstitutionKind : char { const Decl *D = I->first; llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = newScope->LocalDecls[D]; - if (I->second.is<Decl *>()) { - Stored = I->second.get<Decl *>(); + if (auto *D2 = dyn_cast<Decl *>(I->second)) { + Stored = D2; } else { - DeclArgumentPack *OldPack = I->second.get<DeclArgumentPack *>(); + DeclArgumentPack *OldPack = cast<DeclArgumentPack *>(I->second); DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack); Stored = NewPack; newScope->ArgumentPacks.push_back(NewPack); diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index fd834c14ce79..dfd82afad400 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -724,15 +724,20 @@ enum ASTRecordTypes { /// Record code for vtables to emit. VTABLES_TO_EMIT = 70, - /// Record code for the FunctionDecl to lambdas mapping. These lambdas have to - /// be loaded right after the function they belong to. It is required to have - /// canonical declaration for the lambda class from the same module as - /// enclosing function. - FUNCTION_DECL_TO_LAMBDAS_MAP = 71, + /// Record code for related declarations that have to be deserialized together + /// from the same module. + RELATED_DECLS_MAP = 71, /// Record code for Sema's vector of functions/blocks with effects to /// be verified. DECLS_WITH_EFFECTS_TO_VERIFY = 72, + + /// Record code for updated specialization + UPDATE_SPECIALIZATION = 73, + + CXX_ADDED_TEMPLATE_SPECIALIZATION = 74, + + CXX_ADDED_TEMPLATE_PARTIAL_SPECIALIZATION = 75, }; /// Record types used within a source manager block. @@ -1502,6 +1507,12 @@ enum DeclCode { /// An ImplicitConceptSpecializationDecl record. DECL_IMPLICIT_CONCEPT_SPECIALIZATION, + // A decls specilization record. + DECL_SPECIALIZATIONS, + + // A decls specilization record. + DECL_PARTIAL_SPECIALIZATIONS, + DECL_LAST = DECL_IMPLICIT_CONCEPT_SPECIALIZATION }; @@ -2006,6 +2017,13 @@ enum StmtCode { STMT_OPENACC_LOOP_CONSTRUCT, STMT_OPENACC_COMBINED_CONSTRUCT, EXPR_OPENACC_ASTERISK_SIZE, + STMT_OPENACC_DATA_CONSTRUCT, + STMT_OPENACC_ENTER_DATA_CONSTRUCT, + STMT_OPENACC_EXIT_DATA_CONSTRUCT, + STMT_OPENACC_HOST_DATA_CONSTRUCT, + STMT_OPENACC_WAIT_CONSTRUCT, + STMT_OPENACC_INIT_CONSTRUCT, + STMT_OPENACC_SHUTDOWN_CONSTRUCT, // HLSL Constructs EXPR_HLSL_OUT_ARG, diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index f739fe688c11..9f978762a6fb 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -354,6 +354,9 @@ class ASTIdentifierLookupTrait; /// The on-disk hash table(s) used for DeclContext name lookup. struct DeclContextLookupTable; +/// The on-disk hash table(s) used for specialization decls. +struct LazySpecializationInfoLookupTable; + } // namespace reader } // namespace serialization @@ -534,17 +537,14 @@ private: /// namespace as if it is not delayed. DelayedNamespaceOffsetMapTy DelayedNamespaceOffsetMap; - /// Mapping from FunctionDecl IDs to the corresponding lambda IDs. + /// Mapping from main decl ID to the related decls IDs. /// - /// These lambdas have to be loaded right after the function they belong to. - /// It is required to have canonical declaration for lambda class from the - /// same module as enclosing function. This is required to correctly resolve - /// captured variables in the lambda. Without this, due to lazy - /// deserialization, canonical declarations for the function and lambdas can - /// be selected from different modules and DeclRefExprs may refer to the AST - /// nodes that don't exist in the function. - llvm::DenseMap<GlobalDeclID, SmallVector<GlobalDeclID, 4>> - FunctionToLambdasMap; + /// These related decls have to be loaded right after the main decl. + /// It is required to have canonical declaration for related decls from the + /// same module as the enclosing main decl. Without this, due to lazy + /// deserialization, canonical declarations for the main decl and related can + /// be selected from different modules. + llvm::DenseMap<GlobalDeclID, SmallVector<GlobalDeclID, 4>> RelatedDeclsMap; struct PendingUpdateRecord { Decl *D; @@ -632,20 +632,40 @@ private: llvm::DenseMap<const DeclContext *, serialization::reader::DeclContextLookupTable> Lookups; + using SpecLookupTableTy = + llvm::DenseMap<const Decl *, + serialization::reader::LazySpecializationInfoLookupTable>; + /// Map from decls to specialized decls. + SpecLookupTableTy SpecializationsLookups; + /// Split partial specialization from specialization to speed up lookups. + SpecLookupTableTy PartialSpecializationsLookups; + + bool LoadExternalSpecializationsImpl(SpecLookupTableTy &SpecLookups, + const Decl *D); + bool LoadExternalSpecializationsImpl(SpecLookupTableTy &SpecLookups, + const Decl *D, + ArrayRef<TemplateArgument> TemplateArgs); + // Updates for visible decls can occur for other contexts than just the // TU, and when we read those update records, the actual context may not // be available yet, so have this pending map using the ID as a key. It - // will be realized when the context is actually loaded. - struct PendingVisibleUpdate { + // will be realized when the data is actually loaded. + struct UpdateData { ModuleFile *Mod; const unsigned char *Data; }; - using DeclContextVisibleUpdates = SmallVector<PendingVisibleUpdate, 1>; + using DeclContextVisibleUpdates = SmallVector<UpdateData, 1>; /// Updates to the visible declarations of declaration contexts that /// haven't been loaded yet. llvm::DenseMap<GlobalDeclID, DeclContextVisibleUpdates> PendingVisibleUpdates; + using SpecializationsUpdate = SmallVector<UpdateData, 1>; + using SpecializationsUpdateMap = + llvm::DenseMap<GlobalDeclID, SpecializationsUpdate>; + SpecializationsUpdateMap PendingSpecializationsUpdates; + SpecializationsUpdateMap PendingPartialSpecializationsUpdates; + /// The set of C++ or Objective-C classes that have forward /// declarations that have not yet been linked to their definitions. llvm::SmallPtrSet<Decl *, 4> PendingDefinitions; @@ -678,6 +698,11 @@ private: llvm::BitstreamCursor &Cursor, uint64_t Offset, GlobalDeclID ID); + bool ReadSpecializations(ModuleFile &M, llvm::BitstreamCursor &Cursor, + uint64_t Offset, Decl *D, bool IsPartial); + void AddSpecializations(const Decl *D, const unsigned char *Data, + ModuleFile &M, bool IsPartial); + /// A vector containing identifiers that have already been /// loaded. /// @@ -1419,6 +1444,14 @@ public: const serialization::reader::DeclContextLookupTable * getLoadedLookupTables(DeclContext *Primary) const; + /// Get the loaded specializations lookup tables for \p D, + /// if any. + serialization::reader::LazySpecializationInfoLookupTable * + getLoadedSpecializationsLookupTables(const Decl *D, bool IsPartial); + + /// If we have any unloaded specialization for \p D + bool haveUnloadedSpecializations(const Decl *D) const; + private: struct ImportedModule { ModuleFile *Mod; @@ -2076,6 +2109,12 @@ public: unsigned BlockID, uint64_t *StartOfBlockOffset = nullptr); + bool LoadExternalSpecializations(const Decl *D, bool OnlyPartial) override; + + bool + LoadExternalSpecializations(const Decl *D, + ArrayRef<TemplateArgument> TemplateArgs) override; + /// Finds all the visible declarations with a given name. /// The current implementation of this method just loads the entire /// lookup table as unmaterialized references. diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index e418fdea44a0..adb7cce522a8 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -230,13 +230,12 @@ private: /// instead of comparing the result of `getDeclID()` or `GetDeclRef()`. llvm::SmallPtrSet<const Decl *, 32> PredefinedDecls; - /// Mapping from FunctionDecl ID to the list of lambda IDs inside the - /// function. + /// Mapping from the main decl to related decls inside the main decls. /// - /// These lambdas have to be loaded right after the function they belong to. - /// In order to have canonical declaration for lambda class from the same - /// module as enclosing function during deserialization. - llvm::DenseMap<LocalDeclID, SmallVector<LocalDeclID, 4>> FunctionToLambdasMap; + /// These related decls have to be loaded right after the main decl they + /// belong to. In order to have canonical declaration for related decls from + /// the same module as the main decl during deserialization. + llvm::DenseMap<LocalDeclID, SmallVector<LocalDeclID, 4>> RelatedDeclsMap; /// Offset of each declaration in the bitstream, indexed by /// the declaration's ID. @@ -423,6 +422,13 @@ private: /// Only meaningful for reduced BMI. DeclUpdateMap DeclUpdatesFromGMF; + /// Mapping from decl templates and its new specialization in the + /// current TU. + using SpecializationUpdateMap = + llvm::MapVector<const NamedDecl *, SmallVector<const Decl *>>; + SpecializationUpdateMap SpecializationsUpdates; + SpecializationUpdateMap PartialSpecializationsUpdates; + using FirstLatestDeclMap = llvm::DenseMap<Decl *, Decl *>; /// Map of first declarations from a chained PCH that point to the @@ -575,6 +581,12 @@ private: bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC); + void GenerateSpecializationInfoLookupTable( + const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations, + llvm::SmallVectorImpl<char> &LookupTable, bool IsPartial); + uint64_t WriteSpecializationInfoLookupTable( + const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations, + bool IsPartial); void GenerateNameLookupTable(ASTContext &Context, const DeclContext *DC, llvm::SmallVectorImpl<char> &LookupTable); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, @@ -590,6 +602,7 @@ private: void WriteDeclAndTypes(ASTContext &Context); void PrepareWritingSpecialDecls(Sema &SemaRef); void WriteSpecialDeclRecords(Sema &SemaRef); + void WriteSpecializationsUpdates(bool IsPartial); void WriteDeclUpdatesBlocks(ASTContext &Context, RecordDataImpl &OffsetsRecord); void WriteDeclContextVisibleUpdate(ASTContext &Context, @@ -619,6 +632,9 @@ private: unsigned DeclEnumAbbrev = 0; unsigned DeclObjCIvarAbbrev = 0; unsigned DeclCXXMethodAbbrev = 0; + unsigned DeclSpecializationsAbbrev = 0; + unsigned DeclPartialSpecializationsAbbrev = 0; + unsigned DeclDependentNonTemplateCXXMethodAbbrev = 0; unsigned DeclTemplateCXXMethodAbbrev = 0; unsigned DeclMemberSpecializedCXXMethodAbbrev = 0; @@ -981,13 +997,15 @@ protected: virtual Module *getEmittingModule(ASTContext &Ctx) override; CXX20ModulesGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache, - StringRef OutputFile, bool GeneratingReducedBMI); + StringRef OutputFile, bool GeneratingReducedBMI, + bool AllowASTWithErrors); public: CXX20ModulesGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache, - StringRef OutputFile) + StringRef OutputFile, bool AllowASTWithErrors = false) : CXX20ModulesGenerator(PP, ModuleCache, OutputFile, - /*GeneratingReducedBMI=*/false) {} + /*GeneratingReducedBMI=*/false, + AllowASTWithErrors) {} void HandleTranslationUnit(ASTContext &Ctx) override; }; @@ -997,9 +1015,10 @@ class ReducedBMIGenerator : public CXX20ModulesGenerator { public: ReducedBMIGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache, - StringRef OutputFile) + StringRef OutputFile, bool AllowASTWithErrors = false) : CXX20ModulesGenerator(PP, ModuleCache, OutputFile, - /*GeneratingReducedBMI=*/true) {} + /*GeneratingReducedBMI=*/true, + AllowASTWithErrors) {} }; /// If we can elide the definition of \param D in reduced BMI. diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 9be82622f264..b34e940682fc 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -1749,6 +1749,10 @@ def UncountedLambdaCapturesChecker : Checker<"UncountedLambdaCapturesChecker">, let ParentPackage = WebKitAlpha in { +def MemoryUnsafeCastChecker : Checker<"MemoryUnsafeCastChecker">, + HelpText<"Check for memory unsafe casts from base type to derived type.">, + Documentation<HasDocumentation>; + def NoUncheckedPtrMemberChecker : Checker<"NoUncheckedPtrMemberChecker">, HelpText<"Check for no unchecked member variables.">, Documentation<HasDocumentation>; diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def index ad2dbffe8832..d8a7c755c959 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def @@ -189,20 +189,29 @@ ANALYZER_OPTION( "crosscheck-with-z3-eqclass-timeout-threshold", "Set a timeout for bug report equivalence classes in milliseconds. " "If we exhaust this threshold, we will drop the bug report eqclass " - "instead of doing more Z3 queries. Set 0 for no timeout.", 700) + "instead of doing more Z3 queries. Setting this to 700 ms in conjunction " + "with \"crosscheck-with-z3-timeout-threshold\" of 300 ms, would nicely " + "guarantee that no bug report equivalence class can take longer than " + "1 second, effectively mitigating Z3 hangs during refutation. " + "Set 0 for no timeout.", 0) ANALYZER_OPTION( unsigned, Z3CrosscheckTimeoutThreshold, "crosscheck-with-z3-timeout-threshold", "Set a timeout for individual Z3 queries in milliseconds. " - "Set 0 for no timeout.", 300) + "On fast machines, 300 worked well in some cases. " + "The lower it is, the higher the chances of having flaky issues. " + "Having no timeout may hang the analyzer indefinitely. " + "Set 0 for no timeout.", 15'000) ANALYZER_OPTION( unsigned, Z3CrosscheckRLimitThreshold, "crosscheck-with-z3-rlimit-threshold", - "Set the Z3 resource limit threshold. This sets a deterministic cutoff " - "point for Z3 queries, as longer queries usually consume more resources. " - "Set 0 for unlimited.", 400'000) + "Set the Z3 resource limit threshold. This sets a supposedly deterministic " + "cutoff point for Z3 queries, as longer queries usually consume more " + "resources. " + "400'000 should on average make Z3 queries run for up to 100ms on modern " + "hardware. Set 0 for unlimited.", 0) ANALYZER_OPTION(bool, ShouldReportIssuesInMainSourceFile, "report-in-main-source-file", diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h new file mode 100644 index 000000000000..84a6bf1406ac --- /dev/null +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h @@ -0,0 +1,64 @@ +//== APSIntPtr.h - Wrapper for APSInt objects owned separately -*- C++ -*--==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSIntPtr_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSIntPtr_H + +#include "llvm/ADT/APSInt.h" +#include "llvm/Support/Compiler.h" + +namespace clang::ento { + +/// A safe wrapper around APSInt objects allocated and owned by +/// \c BasicValueFactory. This just wraps a common llvm::APSInt. +class APSIntPtr { + using APSInt = llvm::APSInt; + +public: + APSIntPtr() = delete; + APSIntPtr(const APSIntPtr &) = default; + APSIntPtr &operator=(const APSIntPtr &) & = default; + ~APSIntPtr() = default; + + /// You should not use this API. + /// If do, ensure that the \p Ptr not going to dangle. + /// Prefer using \c BasicValueFactory::getValue() to get an APSIntPtr object. + static APSIntPtr unsafeConstructor(const APSInt *Ptr) { + return APSIntPtr(Ptr); + } + + LLVM_ATTRIBUTE_RETURNS_NONNULL + const APSInt *get() const { return Ptr; } + /*implicit*/ operator const APSInt &() const { return *get(); } + + APSInt operator-() const { return -*Ptr; } + APSInt operator~() const { return ~*Ptr; } + +#define DEFINE_OPERATOR(OP) \ + bool operator OP(APSIntPtr Other) const { return (*Ptr)OP(*Other.Ptr); } + DEFINE_OPERATOR(>) + DEFINE_OPERATOR(>=) + DEFINE_OPERATOR(<) + DEFINE_OPERATOR(<=) + DEFINE_OPERATOR(==) + DEFINE_OPERATOR(!=) +#undef DEFINE_OPERATOR + + const APSInt &operator*() const { return *Ptr; } + const APSInt *operator->() const { return Ptr; } + +private: + explicit APSIntPtr(const APSInt *Ptr) : Ptr(Ptr) {} + + /// Owned by \c BasicValueFactory. + const APSInt *Ptr; +}; + +} // namespace clang::ento + +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSIntPtr_H diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index ec503b41b381..ef04f9c485e8 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -18,10 +18,11 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/AST/Type.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableList.h" @@ -129,7 +130,7 @@ class BasicValueFactory { // This is private because external clients should use the factory // method that takes a QualType. - const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); + APSIntPtr getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); public: BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc) @@ -140,9 +141,9 @@ public: ASTContext &getContext() const { return Ctx; } - const llvm::APSInt& getValue(const llvm::APSInt& X); - const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned); - const llvm::APSInt& getValue(uint64_t X, QualType T); + APSIntPtr getValue(const llvm::APSInt &X); + APSIntPtr getValue(const llvm::APInt &X, bool isUnsigned); + APSIntPtr getValue(uint64_t X, QualType T); /// Returns the type of the APSInt used to store values of the given QualType. APSIntType getAPSIntType(QualType T) const { @@ -165,79 +166,70 @@ public: /// Convert - Create a new persistent APSInt with the same value as 'From' /// but with the bitwidth and signedness of 'To'. - const llvm::APSInt &Convert(const llvm::APSInt& To, - const llvm::APSInt& From) { + APSIntPtr Convert(const llvm::APSInt &To, const llvm::APSInt &From) { APSIntType TargetType(To); if (TargetType == APSIntType(From)) - return From; + return getValue(From); return getValue(TargetType.convert(From)); } - const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) { + APSIntPtr Convert(QualType T, const llvm::APSInt &From) { APSIntType TargetType = getAPSIntType(T); return Convert(TargetType, From); } - const llvm::APSInt &Convert(APSIntType TargetType, const llvm::APSInt &From) { + APSIntPtr Convert(APSIntType TargetType, const llvm::APSInt &From) { if (TargetType == APSIntType(From)) - return From; + return getValue(From); return getValue(TargetType.convert(From)); } - const llvm::APSInt &getIntValue(uint64_t X, bool isUnsigned) { + APSIntPtr getIntValue(uint64_t X, bool isUnsigned) { QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy; return getValue(X, T); } - const llvm::APSInt &getMaxValue(const llvm::APSInt &v) { + APSIntPtr getMaxValue(const llvm::APSInt &v) { return getValue(APSIntType(v).getMaxValue()); } - const llvm::APSInt &getMinValue(const llvm::APSInt &v) { + APSIntPtr getMinValue(const llvm::APSInt &v) { return getValue(APSIntType(v).getMinValue()); } - const llvm::APSInt &getMaxValue(QualType T) { - return getMaxValue(getAPSIntType(T)); - } + APSIntPtr getMaxValue(QualType T) { return getMaxValue(getAPSIntType(T)); } - const llvm::APSInt &getMinValue(QualType T) { - return getMinValue(getAPSIntType(T)); - } + APSIntPtr getMinValue(QualType T) { return getMinValue(getAPSIntType(T)); } - const llvm::APSInt &getMaxValue(APSIntType T) { - return getValue(T.getMaxValue()); - } + APSIntPtr getMaxValue(APSIntType T) { return getValue(T.getMaxValue()); } - const llvm::APSInt &getMinValue(APSIntType T) { - return getValue(T.getMinValue()); - } + APSIntPtr getMinValue(APSIntType T) { return getValue(T.getMinValue()); } - const llvm::APSInt &Add1(const llvm::APSInt &V) { + APSIntPtr Add1(const llvm::APSInt &V) { llvm::APSInt X = V; ++X; return getValue(X); } - const llvm::APSInt &Sub1(const llvm::APSInt &V) { + APSIntPtr Sub1(const llvm::APSInt &V) { llvm::APSInt X = V; --X; return getValue(X); } - const llvm::APSInt &getZeroWithTypeSize(QualType T) { + APSIntPtr getZeroWithTypeSize(QualType T) { assert(T->isScalarType()); return getValue(0, Ctx.getTypeSize(T), true); } - const llvm::APSInt &getTruthValue(bool b, QualType T) { + APSIntPtr getTruthValue(bool b, QualType T) { return getValue(b ? 1 : 0, Ctx.getIntWidth(T), T->isUnsignedIntegerOrEnumerationType()); } - const llvm::APSInt &getTruthValue(bool b) { + APSIntPtr getTruthValue(bool b) { return getTruthValue(b, Ctx.getLogicalOperationType()); } @@ -273,9 +265,9 @@ public: accumCXXBase(llvm::iterator_range<CastExpr::path_const_iterator> PathRange, const nonloc::PointerToMember &PTM, const clang::CastKind &kind); - const llvm::APSInt* evalAPSInt(BinaryOperator::Opcode Op, - const llvm::APSInt& V1, - const llvm::APSInt& V2); + std::optional<APSIntPtr> evalAPSInt(BinaryOperator::Opcode Op, + const llvm::APSInt &V1, + const llvm::APSInt &V2); const std::pair<SVal, uintptr_t>& getPersistentSValWithData(const SVal& V, uintptr_t Data); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index a6d05a3ac67b..80b79fd4e928 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -126,6 +126,14 @@ private: ExplodedNode *generateCallExitBeginNode(ExplodedNode *N, const ReturnStmt *RS); + /// Helper function called by `HandleBranch()`. If the currently handled + /// branch corresponds to a loop, this returns the number of already + /// completed iterations in that loop, otherwise the return value is + /// `std::nullopt`. Note that this counts _all_ earlier iterations, including + /// ones that were performed within an earlier iteration of an outer loop. + std::optional<unsigned> getCompletedIterationCount(const CFGBlock *B, + ExplodedNode *Pred) const; + public: /// Construct a CoreEngine object to analyze the provided CFG. CoreEngine(ExprEngine &exprengine, diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 8c7493e27fca..20c446e33ef9 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -321,14 +321,14 @@ public: NodeBuilderWithSinks &nodeBuilder, ExplodedNode *Pred); - /// ProcessBranch - Called by CoreEngine. Used to generate successor - /// nodes by processing the 'effects' of a branch condition. - void processBranch(const Stmt *Condition, - NodeBuilderContext& BuilderCtx, - ExplodedNode *Pred, - ExplodedNodeSet &Dst, - const CFGBlock *DstT, - const CFGBlock *DstF); + /// ProcessBranch - Called by CoreEngine. Used to generate successor nodes by + /// processing the 'effects' of a branch condition. If the branch condition + /// is a loop condition, IterationsCompletedInLoop is the number of completed + /// iterations (otherwise it's std::nullopt). + void processBranch(const Stmt *Condition, NodeBuilderContext &BuilderCtx, + ExplodedNode *Pred, ExplodedNodeSet &Dst, + const CFGBlock *DstT, const CFGBlock *DstF, + std::optional<unsigned> IterationsCompletedInLoop); /// Called by CoreEngine. /// Used to generate successor nodes for temporary destructors depending @@ -588,6 +588,8 @@ public: void evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, const Expr *Ex); + bool didEagerlyAssumeBifurcateAt(ProgramStateRef State, const Expr *Ex) const; + static std::pair<const ProgramPointTag *, const ProgramPointTag *> getEagerlyAssumeBifurcationTags(); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 0d9566285f5d..f88bf70d7239 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -1206,7 +1206,7 @@ class ElementRegion : public TypedValueRegion { : TypedValueRegion(sReg, ElementRegionKind), ElementType(elementType), Index(Idx) { assert((!isa<nonloc::ConcreteInt>(Idx) || - Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) && + Idx.castAs<nonloc::ConcreteInt>().getValue()->isSigned()) && "The index must be signed"); assert(!elementType.isNull() && !elementType->isVoidType() && "Invalid region type!"); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 29f534eba2a2..a20516b003c7 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -70,7 +70,6 @@ template <typename T> struct ProgramStateTrait { /// values will never change. class ProgramState : public llvm::FoldingSetNode { public: - typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy; typedef llvm::ImmutableMap<void*, void*> GenericDataMap; private: diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h index 5766af1fc78a..7cfb24e5e649 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h @@ -16,6 +16,7 @@ #include "clang/Basic/JsonSupport.h" #include "clang/Basic/TargetInfo.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h" #include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h" #include <optional> @@ -154,7 +155,7 @@ public: return nullptr; // This is the only solution, store it - return &BVF.getValue(Value); + return BVF.getValue(Value).get(); } if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) { @@ -167,16 +168,16 @@ public: const llvm::APSInt *Value; if (!(Value = getSymVal(State, CastSym))) return nullptr; - return &BVF.Convert(SC->getType(), *Value); + return BVF.Convert(SC->getType(), *Value).get(); } if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) { const llvm::APSInt *LHS, *RHS; if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) { LHS = getSymVal(State, SIE->getLHS()); - RHS = &SIE->getRHS(); + RHS = SIE->getRHS().get(); } else if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) { - LHS = &ISE->getLHS(); + LHS = ISE->getLHS().get(); RHS = getSymVal(State, ISE->getRHS()); } else if (const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) { // Early termination to avoid expensive call @@ -195,7 +196,9 @@ public: std::tie(ConvertedRHS, RTy) = SMTConv::fixAPSInt(Ctx, *RHS); SMTConv::doIntTypeConversion<llvm::APSInt, &SMTConv::castAPSInt>( Solver, Ctx, ConvertedLHS, LTy, ConvertedRHS, RTy); - return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS); + std::optional<APSIntPtr> Res = + BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS); + return Res ? Res.value().get() : nullptr; } llvm_unreachable("Unsupported expression to get symbol value!"); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index ec2b2b245694..54430d426a82 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -329,11 +329,10 @@ public: } nonloc::SymbolVal makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, - const llvm::APSInt &rhs, QualType type); + APSIntPtr rhs, QualType type); - nonloc::SymbolVal makeNonLoc(const llvm::APSInt &rhs, - BinaryOperator::Opcode op, const SymExpr *lhs, - QualType type); + nonloc::SymbolVal makeNonLoc(APSIntPtr rhs, BinaryOperator::Opcode op, + const SymExpr *lhs, QualType type); nonloc::SymbolVal makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType type); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index a054a819a15a..aeb57b28077c 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -17,6 +17,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/FoldingSet.h" @@ -298,9 +299,12 @@ public: /// Value representing integer constant. class ConcreteInt : public NonLoc { public: - explicit ConcreteInt(const llvm::APSInt &V) : NonLoc(ConcreteIntKind, &V) {} + explicit ConcreteInt(APSIntPtr V) : NonLoc(ConcreteIntKind, V.get()) {} - const llvm::APSInt &getValue() const { return *castDataAs<llvm::APSInt>(); } + APSIntPtr getValue() const { + // This is safe because in the ctor we take a safe APSIntPtr. + return APSIntPtr::unsafeConstructor(castDataAs<llvm::APSInt>()); + } static bool classof(SVal V) { return V.getKind() == ConcreteIntKind; } }; @@ -510,9 +514,12 @@ public: class ConcreteInt : public Loc { public: - explicit ConcreteInt(const llvm::APSInt &V) : Loc(ConcreteIntKind, &V) {} + explicit ConcreteInt(APSIntPtr V) : Loc(ConcreteIntKind, V.get()) {} - const llvm::APSInt &getValue() const { return *castDataAs<llvm::APSInt>(); } + APSIntPtr getValue() const { + // This is safe because in the ctor we take a safe APSIntPtr. + return APSIntPtr::unsafeConstructor(castDataAs<llvm::APSInt>()); + } static bool classof(SVal V) { return V.getKind() == ConcreteIntKind; } }; diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 3b64d38ee2b2..73732d532f63 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -18,6 +18,7 @@ #include "clang/AST/Type.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/LLVM.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" @@ -410,9 +411,7 @@ protected: return 1; } - static const llvm::APSInt *getPointer(const llvm::APSInt &Value) { - return &Value; - } + static const llvm::APSInt *getPointer(APSIntPtr Value) { return Value.get(); } static const SymExpr *getPointer(const SymExpr *Value) { return Value; } static void dumpToStreamImpl(raw_ostream &os, const SymExpr *Value); @@ -468,11 +467,11 @@ public: }; /// Represents a symbolic expression like 'x' + 3. -using SymIntExpr = BinarySymExprImpl<const SymExpr *, const llvm::APSInt &, +using SymIntExpr = BinarySymExprImpl<const SymExpr *, APSIntPtr, SymExpr::Kind::SymIntExprKind>; /// Represents a symbolic expression like 3 - 'x'. -using IntSymExpr = BinarySymExprImpl<const llvm::APSInt &, const SymExpr *, +using IntSymExpr = BinarySymExprImpl<APSIntPtr, const SymExpr *, SymExpr::Kind::IntSymExprKind>; /// Represents a symbolic expression like 'x' + 'y'. @@ -537,15 +536,14 @@ public: QualType From, QualType To); const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, - const llvm::APSInt& rhs, QualType t); + APSIntPtr rhs, QualType t); const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op, - const llvm::APSInt& rhs, QualType t) { + APSIntPtr rhs, QualType t) { return getSymIntExpr(&lhs, op, rhs, t); } - const IntSymExpr *getIntSymExpr(const llvm::APSInt& lhs, - BinaryOperator::Opcode op, + const IntSymExpr *getIntSymExpr(APSIntPtr lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t); const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, diff --git a/clang/include/module.modulemap b/clang/include/module.modulemap index b399f0beee59..5bb9f6b7a91f 100644 --- a/clang/include/module.modulemap +++ b/clang/include/module.modulemap @@ -115,7 +115,7 @@ module Clang_Diagnostics { module Driver { header "clang/Driver/DriverDiagnostic.h" export * } module Frontend { header "clang/Frontend/FrontendDiagnostic.h" export * } module Lex { header "clang/Lex/LexDiagnostic.h" export * } - module Parse { header "clang/Parse/ParseDiagnostic.h" export * } + module Parse { header "clang/Basic/DiagnosticParse.h" export * } module Serialization { header "clang/Serialization/SerializationDiagnostic.h" export * } module Refactoring { header "clang/Tooling/Refactoring/RefactoringDiagnostic.h" export * } } @@ -183,9 +183,14 @@ module Clang_StaticAnalyzer_Frontend { module * { export * } } +module Clang_Support { requires cplusplus umbrella "clang/Support" module * { export * } } + module Clang_Testing { requires cplusplus umbrella "clang/Testing" + + textual header "clang/Testing/TestLanguage.def" + module * { export * } } |
