diff options
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/AST')
97 files changed, 8795 insertions, 3527 deletions
diff --git a/contrib/llvm-project/clang/include/clang/AST/APNumericStorage.h b/contrib/llvm-project/clang/include/clang/AST/APNumericStorage.h new file mode 100644 index 000000000000..95eddbcd86e8 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/AST/APNumericStorage.h @@ -0,0 +1,71 @@ +//===--- APNumericStorage.h - Store APInt/APFloat in ASTContext -*- 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_AST_APNUMERICSTORAGE_H +#define LLVM_CLANG_AST_APNUMERICSTORAGE_H + +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" + +namespace clang { +class ASTContext; + +/// Used by IntegerLiteral/FloatingLiteral/EnumConstantDecl to store the +/// numeric without leaking memory. +/// +/// For large floats/integers, APFloat/APInt will allocate memory from the heap +/// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator +/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with +/// the APFloat/APInt values will never get freed. APNumericStorage uses +/// ASTContext's allocator for memory allocation. +class APNumericStorage { + union { + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t *pVal; ///< Used to store the >64 bits integer value. + }; + unsigned BitWidth; + + bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; } + + APNumericStorage(const APNumericStorage &) = delete; + void operator=(const APNumericStorage &) = delete; + +protected: + APNumericStorage() : VAL(0), BitWidth(0) {} + + llvm::APInt getIntValue() const { + unsigned NumWords = llvm::APInt::getNumWords(BitWidth); + if (NumWords > 1) + return llvm::APInt(BitWidth, NumWords, pVal); + else + return llvm::APInt(BitWidth, VAL); + } + void setIntValue(const ASTContext &C, const llvm::APInt &Val); +}; + +class APIntStorage : private APNumericStorage { +public: + llvm::APInt getValue() const { return getIntValue(); } + void setValue(const ASTContext &C, const llvm::APInt &Val) { + setIntValue(C, Val); + } +}; + +class APFloatStorage : private APNumericStorage { +public: + llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const { + return llvm::APFloat(Semantics, getIntValue()); + } + void setValue(const ASTContext &C, const llvm::APFloat &Val) { + setIntValue(C, Val.bitcastToAPInt()); + } +}; + +} // end namespace clang + +#endif // LLVM_CLANG_AST_APNUMERICSTORAGE_H diff --git a/contrib/llvm-project/clang/include/clang/AST/APValue.h b/contrib/llvm-project/clang/include/clang/AST/APValue.h index 5f4ac02f53c9..c4206b73b115 100644 --- a/contrib/llvm-project/clang/include/clang/AST/APValue.h +++ b/contrib/llvm-project/clang/include/clang/AST/APValue.h @@ -238,7 +238,7 @@ public: } }; class LValuePathSerializationHelper { - const void *ElemTy; + const void *Ty; public: ArrayRef<LValuePathEntry> Path; @@ -267,15 +267,19 @@ private: }; struct LV; struct Vec { - APValue *Elts; - unsigned NumElts; - Vec() : Elts(nullptr), NumElts(0) {} + APValue *Elts = nullptr; + unsigned NumElts = 0; + Vec() = default; + Vec(const Vec &) = delete; + Vec &operator=(const Vec &) = delete; ~Vec() { delete[] Elts; } }; struct Arr { APValue *Elts; unsigned NumElts, ArrSize; Arr(unsigned NumElts, unsigned ArrSize); + Arr(const Arr &) = delete; + Arr &operator=(const Arr &) = delete; ~Arr(); }; struct StructData { @@ -283,12 +287,16 @@ private: unsigned NumBases; unsigned NumFields; StructData(unsigned NumBases, unsigned NumFields); + StructData(const StructData &) = delete; + StructData &operator=(const StructData &) = delete; ~StructData(); }; struct UnionData { const FieldDecl *Field; APValue *Value; UnionData(); + UnionData(const UnionData &) = delete; + UnionData &operator=(const UnionData &) = delete; ~UnionData(); }; struct AddrLabelDiffData { diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTConcept.h b/contrib/llvm-project/clang/include/clang/AST/ASTConcept.h index d0526f4fa5c5..5f9aa41d3e6c 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTConcept.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTConcept.h @@ -1,9 +1,8 @@ //===--- ASTConcept.h - Concepts Related AST Data Structures ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -15,15 +14,21 @@ #ifndef LLVM_CLANG_AST_ASTCONCEPT_H #define LLVM_CLANG_AST_ASTCONCEPT_H -#include "clang/AST/Expr.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TemplateBase.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" #include <utility> namespace clang { + class ConceptDecl; -class ConceptSpecializationExpr; +class Expr; +class NamedDecl; +struct PrintingPolicy; /// The result of a constraint satisfaction check, containing the necessary /// information to diagnose an unsatisfied constraint. @@ -46,6 +51,7 @@ public: using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>; bool IsSatisfied = false; + bool ContainsErrors = false; /// \brief Pairs of unsatisfied atomic constraint expressions along with the /// substituted constraint expr, if the template arguments could be @@ -60,6 +66,13 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C, const NamedDecl *ConstraintOwner, ArrayRef<TemplateArgument> TemplateArgs); + + bool HasSubstitutionFailure() { + for (const auto &Detail : Details) + if (Detail.second.dyn_cast<SubstitutionDiagnostic *>()) + return true; + return false; + } }; /// Pairs of unsatisfied atomic constraint expressions along with the @@ -80,6 +93,7 @@ struct ASTConstraintSatisfaction final : UnsatisfiedConstraintRecord> { std::size_t NumRecords; bool IsSatisfied : 1; + bool ContainsErrors : 1; const UnsatisfiedConstraintRecord *begin() const { return getTrailingObjects<UnsatisfiedConstraintRecord>(); @@ -91,15 +105,27 @@ struct ASTConstraintSatisfaction final : ASTConstraintSatisfaction(const ASTContext &C, const ConstraintSatisfaction &Satisfaction); + ASTConstraintSatisfaction(const ASTContext &C, + const ASTConstraintSatisfaction &Satisfaction); static ASTConstraintSatisfaction * Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction); + static ASTConstraintSatisfaction * + Rebuild(const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction); }; -/// \brief Common data class for constructs that reference concepts with -/// template arguments. +/// A reference to a concept and its template args, as it appears in the code. +/// +/// Examples: +/// template <int X> requires is_even<X> int half = X/2; +/// ~~~~~~~~~~ (in ConceptSpecializationExpr) +/// +/// std::input_iterator auto I = Container.begin(); +/// ~~~~~~~~~~~~~~~~~~~ (in AutoTypeLoc) +/// +/// template <std::derives_from<Expr> T> void dump(); +/// ~~~~~~~~~~~~~~~~~~~~~~~ (in TemplateTypeParmDecl) class ConceptReference { -protected: // \brief The optional nested name specifier used when naming the concept. NestedNameSpecifierLoc NestedNameSpec; @@ -123,18 +149,20 @@ protected: /// concept. const ASTTemplateArgumentListInfo *ArgsAsWritten; -public: - ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten) : - NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc), - ConceptName(ConceptNameInfo), FoundDecl(FoundDecl), - NamedConcept(NamedConcept), ArgsAsWritten(ArgsAsWritten) {} + const ASTTemplateArgumentListInfo *ArgsAsWritten) + : NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc), + ConceptName(ConceptNameInfo), FoundDecl(FoundDecl), + NamedConcept(NamedConcept), ArgsAsWritten(ArgsAsWritten) {} - ConceptReference() : NestedNameSpec(), TemplateKWLoc(), ConceptName(), - FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {} +public: + static ConceptReference * + Create(const ASTContext &C, NestedNameSpecifierLoc NNS, + SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, + NamedDecl *FoundDecl, ConceptDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten); const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { return NestedNameSpec; @@ -148,6 +176,26 @@ public: SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; } + SourceLocation getLocation() const { return getConceptNameLoc(); } + + SourceLocation getBeginLoc() const LLVM_READONLY { + // Note that if the qualifier is null the template KW must also be null. + if (auto QualifierLoc = getNestedNameSpecifierLoc()) + return QualifierLoc.getBeginLoc(); + return getConceptNameInfo().getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { + return getTemplateArgsAsWritten() && + getTemplateArgsAsWritten()->getRAngleLoc().isValid() + ? getTemplateArgsAsWritten()->getRAngleLoc() + : getConceptNameInfo().getEndLoc(); + } + + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(getBeginLoc(), getEndLoc()); + } + NamedDecl *getFoundDecl() const { return FoundDecl; } @@ -165,22 +213,32 @@ public: bool hasExplicitTemplateArgs() const { return ArgsAsWritten != nullptr; } + + void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const; + void dump() const; + void dump(llvm::raw_ostream &) const; }; -class TypeConstraint : public ConceptReference { +/// Models the abbreviated syntax to constrain a template type parameter: +/// template <convertible_to<string> T> void print(T object); +/// ~~~~~~~~~~~~~~~~~~~~~~ +/// Semantically, this adds an "immediately-declared constraint" with extra arg: +/// requires convertible_to<T, string> +/// +/// In the C++ grammar, a type-constraint is also used for auto types: +/// convertible_to<string> auto X = ...; +/// We do *not* model these as TypeConstraints, but AutoType(Loc) directly. +class TypeConstraint { /// \brief The immediately-declared constraint expression introduced by this /// type-constraint. Expr *ImmediatelyDeclaredConstraint = nullptr; + ConceptReference *ConceptRef; public: - TypeConstraint(NestedNameSpecifierLoc NNS, - DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, - ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - Expr *ImmediatelyDeclaredConstraint) : - ConceptReference(NNS, /*TemplateKWLoc=*/SourceLocation(), ConceptNameInfo, - FoundDecl, NamedConcept, ArgsAsWritten), - ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint) {} + TypeConstraint(ConceptReference *ConceptRef, + Expr *ImmediatelyDeclaredConstraint) + : ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint), + ConceptRef(ConceptRef) {} /// \brief Get the immediately-declared constraint expression introduced by /// this type-constraint, that is - the constraint expression that is added to @@ -189,7 +247,41 @@ public: return ImmediatelyDeclaredConstraint; } - void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const; + ConceptReference *getConceptReference() const { return ConceptRef; } + + // FIXME: Instead of using these concept related functions the callers should + // directly work with the corresponding ConceptReference. + ConceptDecl *getNamedConcept() const { return ConceptRef->getNamedConcept(); } + + SourceLocation getConceptNameLoc() const { + return ConceptRef->getConceptNameLoc(); + } + + bool hasExplicitTemplateArgs() const { + return ConceptRef->hasExplicitTemplateArgs(); + } + + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { + return ConceptRef->getTemplateArgsAsWritten(); + } + + SourceLocation getTemplateKWLoc() const { + return ConceptRef->getTemplateKWLoc(); + } + + NamedDecl *getFoundDecl() const { return ConceptRef->getFoundDecl(); } + + const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { + return ConceptRef->getNestedNameSpecifierLoc(); + } + + const DeclarationNameInfo &getConceptNameInfo() const { + return ConceptRef->getConceptNameInfo(); + } + + void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const { + ConceptRef->print(OS, Policy); + } }; } // clang diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTConsumer.h b/contrib/llvm-project/clang/include/clang/AST/ASTConsumer.h index ecdd8e873e1e..ebcd8059284d 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTConsumer.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTConsumer.h @@ -33,12 +33,12 @@ namespace clang { class ASTConsumer { /// Whether this AST consumer also requires information about /// semantic analysis. - bool SemaConsumer; + bool SemaConsumer = false; friend class SemaConsumer; public: - ASTConsumer() : SemaConsumer(false) { } + ASTConsumer() = default; virtual ~ASTConsumer() {} @@ -76,7 +76,7 @@ public: virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) {} /// Invoked when a function is implicitly instantiated. - /// Note that at this point point it does not have a body, its body is + /// Note that at this point it does not have a body, its body is /// instantiated at the end of the translation unit and passed to /// HandleTopLevelDecl. virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {} diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTContext.h b/contrib/llvm-project/clang/include/clang/AST/ASTContext.h index 34299581d89d..3e46a5da3fc0 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTContext.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTContext.h @@ -14,65 +14,32 @@ #ifndef LLVM_CLANG_AST_ASTCONTEXT_H #define LLVM_CLANG_AST_ASTCONTEXT_H -#include "clang/AST/ASTContextAllocate.h" #include "clang/AST/ASTFwd.h" #include "clang/AST/CanonicalType.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/ComparisonCategories.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" -#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/RawCommentList.h" #include "clang/AST/TemplateName.h" -#include "clang/AST/Type.h" -#include "clang/Basic/AddressSpaces.h" -#include "clang/Basic/AttrKinds.h" -#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/Linkage.h" -#include "clang/Basic/NoSanitizeList.h" -#include "clang/Basic/OperatorKinds.h" #include "clang/Basic/PartialDiagnostic.h" -#include "clang/Basic/ProfileList.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/Specifiers.h" -#include "clang/Basic/TargetCXXABI.h" -#include "clang/Basic/XRayLists.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/MapVector.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/TinyPtrVector.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/Support/AlignOf.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/TypeSize.h" -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <iterator> -#include <memory> -#include <string> -#include <type_traits> -#include <utility> -#include <vector> +#include <optional> namespace llvm { @@ -90,6 +57,7 @@ class ASTMutationListener; class ASTRecordLayout; class AtomicExpr; class BlockExpr; +struct BlockVarCopyInit; class BuiltinTemplateDecl; class CharUnits; class ConceptDecl; @@ -98,18 +66,19 @@ class CXXConstructorDecl; class CXXMethodDecl; class CXXRecordDecl; class DiagnosticsEngine; -class ParentMapContext; -class DynTypedNode; class DynTypedNodeList; class Expr; +enum class FloatModeKind; class GlobalDecl; -class ItaniumMangleContext; +class IdentifierTable; +class LangOptions; class MangleContext; class MangleNumberingContext; -class MaterializeTemporaryExpr; class MemberSpecializationInfo; class Module; struct MSGuidDeclParts; +class NestedNameSpecifier; +class NoSanitizeList; class ObjCCategoryDecl; class ObjCCategoryImplDecl; class ObjCContainerDecl; @@ -123,9 +92,10 @@ class ObjCPropertyImplDecl; class ObjCProtocolDecl; class ObjCTypeParamDecl; class OMPTraitInfo; +class ParentMapContext; struct ParsedTargetAttr; class Preprocessor; -class Stmt; +class ProfileList; class StoredDeclsMap; class TargetAttr; class TargetInfo; @@ -133,11 +103,12 @@ class TemplateDecl; class TemplateParameterList; class TemplateTemplateParmDecl; class TemplateTypeParmDecl; +class TypeConstraint; class UnresolvedSetIterator; class UsingShadowDecl; class VarTemplateDecl; class VTableContextBase; -struct BlockVarCopyInit; +class XRayFunctionFilter; namespace Builtin { @@ -164,24 +135,46 @@ namespace serialization { template <class> class AbstractTypeReader; } // namespace serialization +enum class AlignRequirementKind { + /// The alignment was not explicit in code. + None, + + /// The alignment comes from an alignment attribute on a typedef. + RequiredByTypedef, + + /// The alignment comes from an alignment attribute on a record type. + RequiredByRecord, + + /// The alignment comes from an alignment attribute on a enum type. + RequiredByEnum, +}; + struct TypeInfo { uint64_t Width = 0; unsigned Align = 0; - bool AlignIsRequired : 1; + AlignRequirementKind AlignRequirement; - TypeInfo() : AlignIsRequired(false) {} - TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired) - : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {} + TypeInfo() : AlignRequirement(AlignRequirementKind::None) {} + TypeInfo(uint64_t Width, unsigned Align, + AlignRequirementKind AlignRequirement) + : Width(Width), Align(Align), AlignRequirement(AlignRequirement) {} + bool isAlignRequired() { + return AlignRequirement != AlignRequirementKind::None; + } }; struct TypeInfoChars { CharUnits Width; CharUnits Align; - bool AlignIsRequired : 1; + AlignRequirementKind AlignRequirement; - TypeInfoChars() : AlignIsRequired(false) {} - TypeInfoChars(CharUnits Width, CharUnits Align, bool AlignIsRequired) - : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {} + TypeInfoChars() : AlignRequirement(AlignRequirementKind::None) {} + TypeInfoChars(CharUnits Width, CharUnits Align, + AlignRequirementKind AlignRequirement) + : Width(Width), Align(Align), AlignRequirement(AlignRequirement) {} + bool isAlignRequired() { + return AlignRequirement != AlignRequirementKind::None; + } }; /// Holds long-lived AST nodes (such as types and decls) that can be @@ -192,7 +185,7 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable SmallVector<Type *, 0> Types; mutable llvm::FoldingSet<ExtQuals> ExtQualNodes; mutable llvm::FoldingSet<ComplexType> ComplexTypes; - mutable llvm::FoldingSet<PointerType> PointerTypes; + mutable llvm::FoldingSet<PointerType> PointerTypes{GeneralTypesLog2InitSize}; mutable llvm::FoldingSet<AdjustedType> AdjustedTypes; mutable llvm::FoldingSet<BlockPointerType> BlockPointerTypes; mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes; @@ -202,20 +195,25 @@ class ASTContext : public RefCountedBase<ASTContext> { ConstantArrayTypes; mutable llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes; mutable std::vector<VariableArrayType*> VariableArrayTypes; - mutable llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes; - mutable llvm::FoldingSet<DependentSizedExtVectorType> - DependentSizedExtVectorTypes; - mutable llvm::FoldingSet<DependentAddressSpaceType> + mutable llvm::ContextualFoldingSet<DependentSizedArrayType, ASTContext &> + DependentSizedArrayTypes; + mutable llvm::ContextualFoldingSet<DependentSizedExtVectorType, ASTContext &> + DependentSizedExtVectorTypes; + mutable llvm::ContextualFoldingSet<DependentAddressSpaceType, ASTContext &> DependentAddressSpaceTypes; mutable llvm::FoldingSet<VectorType> VectorTypes; - mutable llvm::FoldingSet<DependentVectorType> DependentVectorTypes; + mutable llvm::ContextualFoldingSet<DependentVectorType, ASTContext &> + DependentVectorTypes; mutable llvm::FoldingSet<ConstantMatrixType> MatrixTypes; - mutable llvm::FoldingSet<DependentSizedMatrixType> DependentSizedMatrixTypes; + mutable llvm::ContextualFoldingSet<DependentSizedMatrixType, ASTContext &> + DependentSizedMatrixTypes; mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes; mutable llvm::ContextualFoldingSet<FunctionProtoType, ASTContext&> FunctionProtoTypes; - mutable llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes; - mutable llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes; + mutable llvm::ContextualFoldingSet<DependentTypeOfExprType, ASTContext &> + DependentTypeOfExprTypes; + mutable llvm::ContextualFoldingSet<DependentDecltypeType, ASTContext &> + DependentDecltypeTypes; mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; mutable llvm::FoldingSet<ObjCTypeParamType> ObjCTypeParamTypes; mutable llvm::FoldingSet<SubstTemplateTypeParmType> @@ -224,8 +222,11 @@ class ASTContext : public RefCountedBase<ASTContext> { SubstTemplateTypeParmPackTypes; mutable llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&> TemplateSpecializationTypes; - mutable llvm::FoldingSet<ParenType> ParenTypes; - mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes; + mutable llvm::FoldingSet<ParenType> ParenTypes{GeneralTypesLog2InitSize}; + mutable llvm::FoldingSet<UsingType> UsingTypes; + mutable llvm::FoldingSet<TypedefType> TypedefTypes; + mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes{ + GeneralTypesLog2InitSize}; mutable llvm::FoldingSet<DependentNameType> DependentNameTypes; mutable llvm::ContextualFoldingSet<DependentTemplateSpecializationType, ASTContext&> @@ -239,10 +240,12 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable llvm::FoldingSet<DeducedTemplateSpecializationType> DeducedTemplateSpecializationTypes; mutable llvm::FoldingSet<AtomicType> AtomicTypes; - llvm::FoldingSet<AttributedType> AttributedTypes; + mutable llvm::FoldingSet<AttributedType> AttributedTypes; mutable llvm::FoldingSet<PipeType> PipeTypes; - mutable llvm::FoldingSet<ExtIntType> ExtIntTypes; - mutable llvm::FoldingSet<DependentExtIntType> DependentExtIntTypes; + mutable llvm::FoldingSet<BitIntType> BitIntTypes; + mutable llvm::ContextualFoldingSet<DependentBitIntType, ASTContext &> + DependentBitIntTypes; + llvm::FoldingSet<BTFTagAttributedType> BTFTagAttributedTypes; mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; @@ -292,6 +295,10 @@ class ASTContext : public RefCountedBase<ASTContext> { /// Mapping from GUIDs to the corresponding MSGuidDecl. mutable llvm::FoldingSet<MSGuidDecl> MSGuidDecls; + /// Mapping from APValues to the corresponding UnnamedGlobalConstantDecl. + mutable llvm::FoldingSet<UnnamedGlobalConstantDecl> + UnnamedGlobalConstantDecls; + /// Mapping from APValues to the corresponding TemplateParamObjects. mutable llvm::FoldingSet<TemplateParamObjectDecl> TemplateParamObjectDecls; @@ -446,6 +453,13 @@ class ASTContext : public RefCountedBase<ASTContext> { }; llvm::DenseMap<Module*, PerModuleInitializers*> ModuleInitializers; + /// This is the top-level (C++20) Named module we are building. + Module *CurrentCXXNamedModule = nullptr; + + static constexpr unsigned ConstantArrayTypesLog2InitSize = 8; + static constexpr unsigned GeneralTypesLog2InitSize = 9; + static constexpr unsigned FunctionProtoTypesLog2InitSize = 12; + ASTContext &this_() { return *this; } public: @@ -605,9 +619,6 @@ private: std::unique_ptr<CXXABI> ABI; CXXABI *createCXXABI(const TargetInfo &T); - /// The logical -> physical address space map. - const LangASMap *AddrSpaceMap = nullptr; - /// Address space map mangling must be used with language specific /// address spaces (e.g. OpenCL/CUDA) bool AddrSpaceMapMangling; @@ -633,6 +644,20 @@ public: /// Returns the clang bytecode interpreter context. interp::Context &getInterpContext(); + struct CUDAConstantEvalContext { + /// Do not allow wrong-sided variables in constant expressions. + bool NoWrongSidedVars = false; + } CUDAConstantEvalCtx; + struct CUDAConstantEvalContextRAII { + ASTContext &Ctx; + CUDAConstantEvalContext SavedCtx; + CUDAConstantEvalContextRAII(ASTContext &Ctx_, bool NoWrongSidedVars) + : Ctx(Ctx_), SavedCtx(Ctx_.CUDAConstantEvalCtx) { + Ctx_.CUDAConstantEvalCtx.NoWrongSidedVars = NoWrongSidedVars; + } + ~CUDAConstantEvalContextRAII() { Ctx.CUDAConstantEvalCtx = SavedCtx; } + }; + /// Returns the dynamic AST node parent map context. ParentMapContext &getParentMapContext(); @@ -672,6 +697,12 @@ public: SourceManager& getSourceManager() { return SourceMgr; } const SourceManager& getSourceManager() const { return SourceMgr; } + // Cleans up some of the data structures. This allows us to do cleanup + // normally done in the destructor earlier. Renders much of the ASTContext + // unusable, mostly the actual AST nodes, so should be called when we no + // longer need access to the AST. + void cleanup(); + llvm::BumpPtrAllocator &getAllocator() const { return BumpAlloc; } @@ -728,7 +759,8 @@ public: /// getRealTypeForBitwidth - /// sets floating point QualTy according to specified bitwidth. /// Returns empty type if there is no appropriate target types. - QualType getRealTypeForBitwidth(unsigned DestWidth, bool ExplicitIEEE) const; + QualType getRealTypeForBitwidth(unsigned DestWidth, + FloatModeKind ExplicitType) const; bool AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const; @@ -1024,6 +1056,12 @@ public: /// Get the initializations to perform when importing a module, if any. ArrayRef<Decl*> getModuleInitializers(Module *M); + /// Set the (C++20) module we are building. + void setCurrentNamedModule(Module *M); + + /// Get module under construction, nullptr if this is not a C++20 module. + Module *getCurrentNamedModule() const { return CurrentCXXNamedModule; } + TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl->getMostRecentDecl(); } @@ -1054,7 +1092,7 @@ public: CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; CanQualType UnsignedLongLongTy, UnsignedInt128Ty; - CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty; + CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty, Ibm128Ty; CanQualType ShortAccumTy, AccumTy, LongAccumTy; // ISO/IEC JTC1 SC22 WG14 N1169 Extension CanQualType UnsignedShortAccumTy, UnsignedAccumTy, UnsignedLongAccumTy; @@ -1069,8 +1107,6 @@ public: CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON CanQualType BFloat16Ty; CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3 - CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; - CanQualType Float128ComplexTy; CanQualType VoidPtrTy, NullPtrTy; CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy; CanQualType BuiltinFnTy; @@ -1096,6 +1132,8 @@ public: #define RVV_TYPE(Name, Id, SingletonId) \ CanQualType SingletonId; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) CanQualType SingletonId; +#include "clang/Basic/WebAssemblyReferenceTypes.def" // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. mutable QualType AutoDeductTy; // Deduction against 'auto'. @@ -1109,8 +1147,19 @@ public: mutable TagDecl *MSGuidTagDecl = nullptr; /// Keep track of CUDA/HIP device-side variables ODR-used by host code. + /// This does not include extern shared variables used by device host + /// functions as addresses of shared variables are per warp, therefore + /// cannot be accessed by host code. llvm::DenseSet<const VarDecl *> CUDADeviceVarODRUsedByHost; + /// Keep track of CUDA/HIP external kernels or device variables ODR-used by + /// host code. + llvm::DenseSet<const ValueDecl *> CUDAExternalDeviceDeclODRUsedByHost; + + /// Keep track of CUDA/HIP implicit host device functions used on device side + /// in device compilation. + llvm::DenseSet<const FunctionDecl *> CUDAImplicitHostDeviceFunUsedByDevice; + ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, TranslationUnitKind TUKind); @@ -1152,8 +1201,9 @@ public: /// Create a new implicit TU-level CXXRecordDecl or RecordDecl /// declaration. - RecordDecl *buildImplicitRecord(StringRef Name, - RecordDecl::TagKind TK = TTK_Struct) const; + RecordDecl *buildImplicitRecord( + StringRef Name, + RecordDecl::TagKind TK = RecordDecl::TagKind::Struct) const; /// Create a new implicit TU-level typedef declaration. TypedefDecl *buildImplicitTypedef(QualType T, StringRef Name) const; @@ -1253,11 +1303,11 @@ public: /// declaration of a function with an exception specification is permitted /// and preserved. Other type sugar (for instance, typedefs) is not. QualType getFunctionTypeWithExceptionSpec( - QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI); + QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI) const; /// Determine whether two function types are the same, ignoring /// exception specifications in cases where they're part of the type. - bool hasSameFunctionTypeIgnoringExceptionSpec(QualType T, QualType U); + bool hasSameFunctionTypeIgnoringExceptionSpec(QualType T, QualType U) const; /// Change the exception specification on a function once it is /// delay-parsed, instantiated, or computed. @@ -1303,6 +1353,9 @@ public: CanQualType getDecayedType(CanQualType T) const { return CanQualType::CreateUnsafe(getDecayedType((QualType) T)); } + /// Return the uniqued reference to a specified decay from the original + /// type to the decayed type. + QualType getDecayedType(QualType Orig, QualType Decayed) const; /// Return the uniqued reference to the atomic type for the specified /// type. @@ -1322,13 +1375,13 @@ public: /// Return a write_only pipe type for the specified type. QualType getWritePipeType(QualType T) const; - /// Return an extended integer type with the specified signedness and bit + /// Return a bit-precise integer type with the specified signedness and bit /// count. - QualType getExtIntType(bool Unsigned, unsigned NumBits) const; + QualType getBitIntType(bool Unsigned, unsigned NumBits) const; - /// Return a dependent extended integer type with the specified signedness and - /// bit count. - QualType getDependentExtIntType(bool Unsigned, Expr *BitsExpr) const; + /// Return a dependent bit-precise integer type with the specified signedness + /// and bit count. + QualType getDependentBitIntType(bool Unsigned, Expr *BitsExpr) const; /// Gets the struct used to keep track of the extended descriptor for /// pointer to blocks. @@ -1340,6 +1393,12 @@ public: /// Get address space for OpenCL type. LangAS getOpenCLTypeAddrSpace(const Type *T) const; + /// Returns default address space based on OpenCL version and enabled features + inline LangAS getDefaultOpenCLPointeeAddrSpace() { + return LangOpts.OpenCLGenericAddressSpace ? LangAS::opencl_generic + : LangAS::opencl_private; + } + void setcudaConfigureCallDecl(FunctionDecl *FD) { cudaConfigureCallDecl = FD; } @@ -1376,8 +1435,7 @@ public: /// Return a non-unique reference to the type for a variable array of /// the specified element type. QualType getVariableArrayType(QualType EltTy, Expr *NumElts, - ArrayType::ArraySizeModifier ASM, - unsigned IndexTypeQuals, + ArraySizeModifier ASM, unsigned IndexTypeQuals, SourceRange Brackets) const; /// Return a non-unique reference to the type for a dependently-sized @@ -1386,21 +1444,19 @@ public: /// FIXME: We will need these to be uniqued, or at least comparable, at some /// point. QualType getDependentSizedArrayType(QualType EltTy, Expr *NumElts, - ArrayType::ArraySizeModifier ASM, + ArraySizeModifier ASM, unsigned IndexTypeQuals, SourceRange Brackets) const; /// Return a unique reference to the type for an incomplete array of /// the specified element type. - QualType getIncompleteArrayType(QualType EltTy, - ArrayType::ArraySizeModifier ASM, + QualType getIncompleteArrayType(QualType EltTy, ArraySizeModifier ASM, unsigned IndexTypeQuals) const; /// Return the unique reference to the type for a constant array of /// the specified element type. QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, - const Expr *SizeExpr, - ArrayType::ArraySizeModifier ASM, + const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const; /// Return a type for a constant array for a string literal of the @@ -1427,21 +1483,27 @@ public: /// Return the unique reference to a scalable vector type of the specified /// element type and scalable number of elements. + /// For RISC-V, number of fields is also provided when it fetching for + /// tuple type. /// /// \pre \p EltTy must be a built-in type. - QualType getScalableVectorType(QualType EltTy, unsigned NumElts) const; + QualType getScalableVectorType(QualType EltTy, unsigned NumElts, + unsigned NumFields = 1) const; + + /// Return a WebAssembly externref type. + QualType getWebAssemblyExternrefType() const; /// Return the unique reference to a vector type of the specified /// element type and size. /// /// \pre \p VectorType must be a built-in type. QualType getVectorType(QualType VectorType, unsigned NumElts, - VectorType::VectorKind VecKind) const; + VectorKind VecKind) const; /// Return the unique reference to the type for a dependently sized vector of /// the specified element type. QualType getDependentVectorType(QualType VectorType, Expr *SizeExpr, SourceLocation AttrLoc, - VectorType::VectorKind VecKind) const; + VectorKind VecKind) const; /// Return the unique reference to an extended vector type /// of the specified element type and size. @@ -1497,6 +1559,12 @@ private: QualType getFunctionTypeInternal(QualType ResultTy, ArrayRef<QualType> Args, const FunctionProtoType::ExtProtoInfo &EPI, bool OnlyWantCanonical) const; + QualType + getAutoTypeInternal(QualType DeducedType, AutoTypeKeyword Keyword, + bool IsDependent, bool IsPack = false, + ConceptDecl *TypeConstraintConcept = nullptr, + ArrayRef<TemplateArgument> TypeConstraintArgs = {}, + bool IsCanon = false) const; public: /// Return the unique reference to the type for the specified type @@ -1515,6 +1583,9 @@ public: return getTypeDeclTypeSlow(Decl); } + QualType getUsingType(const UsingShadowDecl *Found, + QualType Underlying) const; + /// Return the unique reference to the type for the specified /// typedef-name decl. QualType getTypedefType(const TypedefNameDecl *Decl, @@ -1524,16 +1595,23 @@ public: QualType getEnumType(const EnumDecl *Decl) const; + QualType + getUnresolvedUsingType(const UnresolvedUsingTypenameDecl *Decl) const; + QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const; - QualType getAttributedType(attr::Kind attrKind, - QualType modifiedType, - QualType equivalentType); + QualType getAttributedType(attr::Kind attrKind, QualType modifiedType, + QualType equivalentType) const; - QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced, - QualType Replacement) const; - QualType getSubstTemplateTypeParmPackType( - const TemplateTypeParmType *Replaced, + QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr, + QualType Wrapped); + + QualType + getSubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl, + unsigned Index, + std::optional<unsigned> PackIndex) const; + QualType getSubstTemplateTypeParmPackType(Decl *AssociatedDecl, + unsigned Index, bool Final, const TemplateArgument &ArgPack); QualType @@ -1550,7 +1628,7 @@ public: ArrayRef<TemplateArgument> Args) const; QualType getTemplateSpecializationType(TemplateName T, - const TemplateArgumentListInfo &Args, + ArrayRef<TemplateArgumentLoc> Args, QualType Canon = QualType()) const; TypeSourceInfo * @@ -1571,10 +1649,9 @@ public: const IdentifierInfo *Name, QualType Canon = QualType()) const; - QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const IdentifierInfo *Name, - const TemplateArgumentListInfo &Args) const; + QualType getDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + const IdentifierInfo *Name, ArrayRef<TemplateArgumentLoc> Args) const; QualType getDependentTemplateSpecializationType( ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args) const; @@ -1595,7 +1672,7 @@ public: /// elsewhere, such as if the pattern contains a placeholder type or /// if this is the canonical type of another pack expansion type. QualType getPackExpansionType(QualType Pattern, - Optional<unsigned> NumExpansions, + std::optional<unsigned> NumExpansions, bool ExpectPackInType = true); QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, @@ -1627,9 +1704,11 @@ public: /// Return a ObjCObjectPointerType type for the given ObjCObjectType. QualType getObjCObjectPointerType(QualType OIT) const; - /// GCC extension. - QualType getTypeOfExprType(Expr *e) const; - QualType getTypeOfType(QualType t) const; + /// C23 feature and GCC extension. + QualType getTypeOfExprType(Expr *E, TypeOfKind Kind) const; + QualType getTypeOfType(QualType QT, TypeOfKind Kind) const; + + QualType getReferenceQualifiedType(const Expr *e) const; /// C++11 decltype. QualType getDecltypeType(Expr *e, QualType UnderlyingType) const; @@ -1650,6 +1729,10 @@ public: /// C++11 deduction pattern for 'auto &&' type. QualType getAutoRRefDeductType() const; + /// Remove any type constraints from a template parameter type, for + /// equivalence comparison of template parameters. + QualType getUnconstrainedType(QualType T) const; + /// C++17 deduced class template specialization type. QualType getDeducedTemplateSpecializationType(TemplateName Template, QualType DeducedType, @@ -2106,16 +2189,20 @@ public: TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, - TemplateDecl *Template) const; + TemplateName Template) const; TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, const IdentifierInfo *Name) const; TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, OverloadedOperatorKind Operator) const; - TemplateName getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param, - TemplateName replacement) const; - TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, - const TemplateArgument &ArgPack) const; + TemplateName + getSubstTemplateTemplateParm(TemplateName replacement, Decl *AssociatedDecl, + unsigned Index, + std::optional<unsigned> PackIndex) const; + TemplateName getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack, + Decl *AssociatedDecl, + unsigned Index, + bool Final) const; enum GetBuiltinTypeError { /// No error @@ -2179,6 +2266,17 @@ public: /// false otherwise. bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType); + /// Return true if the given types are an RISC-V vector builtin type and a + /// VectorType that is a fixed-length representation of the RISC-V vector + /// builtin type for a specific vector-length. + bool areCompatibleRVVTypes(QualType FirstType, QualType SecondType); + + /// Return true if the given vector types are lax-compatible RISC-V vector + /// types as defined by -flax-vector-conversions=, which permits implicit + /// conversions between vectors with different number of elements and/or + /// incompatible element types, false otherwise. + bool areLaxCompatibleRVVTypes(QualType FirstType, QualType SecondType); + /// Return true if the type has been explicitly qualified with ObjC ownership. /// A type may be implicitly qualified with ownership under ObjC ARC, and in /// some cases the compiler treats these differently. @@ -2225,13 +2323,13 @@ public: CharUnits getTypeSizeInChars(QualType T) const; CharUnits getTypeSizeInChars(const Type *T) const; - Optional<CharUnits> getTypeSizeInCharsIfKnown(QualType Ty) const { + std::optional<CharUnits> getTypeSizeInCharsIfKnown(QualType Ty) const { if (Ty->isIncompleteType() || Ty->isDependentType()) - return None; + return std::nullopt; return getTypeSizeInChars(Ty); } - Optional<CharUnits> getTypeSizeInCharsIfKnown(const Type *Ty) const { + std::optional<CharUnits> getTypeSizeInCharsIfKnown(const Type *Ty) const { return getTypeSizeInCharsIfKnown(QualType(Ty, 0)); } @@ -2287,6 +2385,9 @@ public: bool isAlignmentRequired(const Type *T) const; bool isAlignmentRequired(QualType T) const; + /// More type predicates useful for type checking/promotion + bool isPromotableIntegerType(QualType T) const; // C99 6.3.1.1p2 + /// Return the "preferred" alignment of the specified type \p T for /// the current target, in bits. /// @@ -2415,7 +2516,9 @@ public: /// Return true if the specified type has unique object representations /// according to (C++17 [meta.unary.prop]p9) - bool hasUniqueObjectRepresentations(QualType Ty) const; + bool + hasUniqueObjectRepresentations(QualType Ty, + bool CheckIfTriviallyCopyable = true) const; //===--------------------------------------------------------------------===// // Type Operators @@ -2452,6 +2555,9 @@ public: return getCanonicalType(T1) == getCanonicalType(T2); } + /// Determine whether the given expressions \p X and \p Y are equivalent. + bool hasSameExpr(const Expr *X, const Expr *Y) const; + /// Return this type as a completely-unqualified array type, /// capturing the qualifiers in \p Quals. /// @@ -2476,9 +2582,9 @@ public: bool hasSameNullabilityTypeQualifier(QualType SubT, QualType SuperT, bool IsParam) const { - auto SubTnullability = SubT->getNullability(*this); - auto SuperTnullability = SuperT->getNullability(*this); - if (SubTnullability.hasValue() == SuperTnullability.hasValue()) { + auto SubTnullability = SubT->getNullability(); + auto SuperTnullability = SuperT->getNullability(); + if (SubTnullability.has_value() == SuperTnullability.has_value()) { // Neither has nullability; return true if (!SubTnullability) return true; @@ -2505,8 +2611,10 @@ public: bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, const ObjCMethodDecl *MethodImp); - bool UnwrapSimilarTypes(QualType &T1, QualType &T2); - void UnwrapSimilarArrayTypes(QualType &T1, QualType &T2); + bool UnwrapSimilarTypes(QualType &T1, QualType &T2, + bool AllowPiMismatch = true); + void UnwrapSimilarArrayTypes(QualType &T1, QualType &T2, + bool AllowPiMismatch = true); /// Determine if two types are similar, according to the C++ rules. That is, /// determine if they are the same other than qualifiers on the initial @@ -2569,11 +2677,40 @@ public: /// template name uses the shortest form of the dependent /// nested-name-specifier, which itself contains all canonical /// types, values, and templates. - TemplateName getCanonicalTemplateName(TemplateName Name) const; + TemplateName getCanonicalTemplateName(const TemplateName &Name) const; /// Determine whether the given template names refer to the same /// template. - bool hasSameTemplateName(TemplateName X, TemplateName Y); + bool hasSameTemplateName(const TemplateName &X, const TemplateName &Y) const; + + /// Determine whether the two declarations refer to the same entity. + bool isSameEntity(const NamedDecl *X, const NamedDecl *Y) const; + + /// Determine whether two template parameter lists are similar enough + /// that they may be used in declarations of the same template. + bool isSameTemplateParameterList(const TemplateParameterList *X, + const TemplateParameterList *Y) const; + + /// Determine whether two template parameters are similar enough + /// that they may be used in declarations of the same template. + bool isSameTemplateParameter(const NamedDecl *X, const NamedDecl *Y) const; + + /// Determine whether two 'requires' expressions are similar enough that they + /// may be used in re-declarations. + /// + /// Use of 'requires' isn't mandatory, works with constraints expressed in + /// other ways too. + bool isSameConstraintExpr(const Expr *XCE, const Expr *YCE) const; + + /// Determine whether two type contraint are similar enough that they could + /// used in declarations of the same template. + bool isSameTypeConstraint(const TypeConstraint *XTC, + const TypeConstraint *YTC) const; + + /// Determine whether two default template arguments are similar enough + /// that they may be used in declarations of the same template. + bool isSameDefaultTemplateArgument(const NamedDecl *X, + const NamedDecl *Y) const; /// Retrieve the "canonical" template argument. /// @@ -2614,6 +2751,10 @@ public: /// Return number of constant array elements. uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const; + /// Return number of elements initialized in an ArrayInitLoopExpr. + uint64_t + getArrayInitLoopExprElementCount(const ArrayInitLoopExpr *AILE) const; + /// Perform adjustment on the parameter type of a function. /// /// This routine adjusts the given parameter type @p T to the actual @@ -2671,22 +2812,6 @@ public: /// long double and double on AArch64 will return 0). int getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const; - /// Return a real floating point or a complex type (based on - /// \p typeDomain/\p typeSize). - /// - /// \param typeDomain a real floating point or complex type. - /// \param typeSize a real floating point or complex type. - QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize, - QualType typeDomain) const; - - unsigned getTargetAddressSpace(QualType T) const { - return getTargetAddressSpace(T.getQualifiers()); - } - - unsigned getTargetAddressSpace(Qualifiers Q) const { - return getTargetAddressSpace(Q.getAddressSpace()); - } - unsigned getTargetAddressSpace(LangAS AS) const; LangAS getLangASForBuiltinAddressSpace(unsigned AS) const; @@ -2699,6 +2824,23 @@ public: return AddrSpaceMapMangling || isTargetAddressSpace(AS); } + // Merges two exception specifications, such that the resulting + // exception spec is the union of both. For example, if either + // of them can throw something, the result can throw it as well. + FunctionProtoType::ExceptionSpecInfo + mergeExceptionSpecs(FunctionProtoType::ExceptionSpecInfo ESI1, + FunctionProtoType::ExceptionSpecInfo ESI2, + SmallVectorImpl<QualType> &ExceptionTypeStorage, + bool AcceptDependent); + + // For two "same" types, return a type which has + // the common sugar between them. If Unqualified is true, + // both types need only be the same unqualified type. + // The result will drop the qualifiers which do not occur + // in both types. + QualType getCommonSugaredType(QualType X, QualType Y, + bool Unqualified = false); + private: // Helper for integer ordering unsigned getIntegerRank(const Type *T) const; @@ -2716,14 +2858,20 @@ public: bool typesAreBlockPointerCompatible(QualType, QualType); bool isObjCIdType(QualType T) const { + if (const auto *ET = dyn_cast<ElaboratedType>(T)) + T = ET->getNamedType(); return T == getObjCIdType(); } bool isObjCClassType(QualType T) const { + if (const auto *ET = dyn_cast<ElaboratedType>(T)) + T = ET->getNamedType(); return T == getObjCClassType(); } bool isObjCSelType(QualType T) const { + if (const auto *ET = dyn_cast<ElaboratedType>(T)) + T = ET->getNamedType(); return T == getObjCSelType(); } @@ -2749,10 +2897,12 @@ public: bool canBindObjCObjectType(QualType To, QualType From); // Functions for calculating composite types - QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false, - bool Unqualified = false, bool BlockReturnType = false); - QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, - bool Unqualified = false, bool AllowCXX = false); + QualType mergeTypes(QualType, QualType, bool OfBlockPointer = false, + bool Unqualified = false, bool BlockReturnType = false, + bool IsConditionalOperator = false); + QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer = false, + bool Unqualified = false, bool AllowCXX = false, + bool IsConditionalOperator = false); QualType mergeFunctionParameterTypes(QualType, QualType, bool OfBlockPointer = false, bool Unqualified = false); @@ -2923,7 +3073,7 @@ public: } GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const; - GVALinkage GetGVALinkageForVariable(const VarDecl *VD); + GVALinkage GetGVALinkageForVariable(const VarDecl *VD) const; /// Determines if the decl can be CodeGen'ed or deserialized from PCH /// lazily, only when used; this is only relevant for function or file scoped @@ -2954,7 +3104,8 @@ public: DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD); void setManglingNumber(const NamedDecl *ND, unsigned Number); - unsigned getManglingNumber(const NamedDecl *ND) const; + unsigned getManglingNumber(const NamedDecl *ND, + bool ForAuxTarget = false) const; void setStaticLocalNumber(const VarDecl *VD, unsigned Number); unsigned getStaticLocalNumber(const VarDecl *VD) const; @@ -2985,6 +3136,11 @@ public: /// GUID value. MSGuidDecl *getMSGuidDecl(MSGuidDeclParts Parts) const; + /// Return a declaration for a uniquified anonymous global constant + /// corresponding to a given APValue. + UnnamedGlobalConstantDecl * + getUnnamedGlobalConstantDecl(QualType Ty, const APValue &Value) const; + /// Return the template parameter object of the given type with the given /// value. TemplateParamObjectDecl *getTemplateParamObjectDecl(QualType T, @@ -2994,6 +3150,9 @@ public: /// valid feature names. ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const; + std::vector<std::string> + filterFunctionTargetVersionAttrs(const TargetVersionAttr *TV) const; + void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, const FunctionDecl *) const; void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, @@ -3065,7 +3224,6 @@ private: public: ObjCEncOptions() : Bits(0) {} - ObjCEncOptions(const ObjCEncOptions &RHS) : Bits(RHS.Bits) {} #define OPT_LIST(V) \ V(ExpandPointedToStructures, 0) \ @@ -3086,11 +3244,11 @@ OPT_LIST(V) #undef OPT_LIST - LLVM_NODISCARD ObjCEncOptions keepingOnly(ObjCEncOptions Mask) const { + [[nodiscard]] ObjCEncOptions keepingOnly(ObjCEncOptions Mask) const { return Bits & Mask.Bits; } - LLVM_NODISCARD ObjCEncOptions forComponentType() const { + [[nodiscard]] ObjCEncOptions forComponentType() const { ObjCEncOptions Mask = ObjCEncOptions() .setIsOutermostType() .setIsStructField(); @@ -3201,39 +3359,18 @@ public: /// Return a new OMPTraitInfo object owned by this context. OMPTraitInfo &getNewOMPTraitInfo(); - /// Whether a C++ static variable may be externalized. - bool mayExternalizeStaticVar(const Decl *D) const; + /// Whether a C++ static variable or CUDA/HIP kernel may be externalized. + bool mayExternalize(const Decl *D) const; - /// Whether a C++ static variable should be externalized. - bool shouldExternalizeStaticVar(const Decl *D) const; + /// Whether a C++ static variable or CUDA/HIP kernel should be externalized. + bool shouldExternalize(const Decl *D) const; StringRef getCUIDHash() const; - void AddSYCLKernelNamingDecl(const CXXRecordDecl *RD); - bool IsSYCLKernelNamingDecl(const NamedDecl *RD) const; - unsigned GetSYCLKernelNamingIndex(const NamedDecl *RD); - /// A SourceLocation to store whether we have evaluated a kernel name already, - /// and where it happened. If so, we need to diagnose an illegal use of the - /// builtin. - llvm::MapVector<const SYCLUniqueStableNameExpr *, std::string> - SYCLUniqueStableNameEvaluatedValues; - private: /// All OMPTraitInfo objects live in this collection, one per /// `pragma omp [begin] declare variant` directive. SmallVector<std::unique_ptr<OMPTraitInfo>, 4> OMPTraitInfoVector; - - /// A list of the (right now just lambda decls) declarations required to - /// name all the SYCL kernels in the translation unit, so that we can get the - /// correct kernel name, as well as implement - /// __builtin_sycl_unique_stable_name. - llvm::DenseMap<const DeclContext *, - llvm::SmallPtrSet<const CXXRecordDecl *, 4>> - SYCLKernelNamingTypes; - std::unique_ptr<ItaniumMangleContext> SYCLKernelFilterContext; - void FilterSYCLKernelNamingDecls( - const CXXRecordDecl *RD, - llvm::SmallVectorImpl<const CXXRecordDecl *> &Decls); }; /// Insertion operator for diagnostics. diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTDiagnostic.h b/contrib/llvm-project/clang/include/clang/AST/ASTDiagnostic.h index d6549e12d92a..ef2224982862 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTDiagnostic.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTDiagnostic.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_AST_ASTDIAGNOSTIC_H #define LLVM_CLANG_AST_ASTDIAGNOSTIC_H +#include "clang/AST/Type.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticAST.h" @@ -31,6 +32,12 @@ namespace clang { SmallVectorImpl<char> &Output, void *Cookie, ArrayRef<intptr_t> QualTypeVals); + + /// Returns a desugared version of the QualType, and marks ShouldAKA as true + /// whenever we remove significant sugar from the type. Make sure ShouldAKA + /// is initialized before passing it in. + QualType desugarForDiagnostic(ASTContext &Context, QualType QT, + bool &ShouldAKA); } // end namespace clang #endif diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTDumper.h b/contrib/llvm-project/clang/include/clang/AST/ASTDumper.h index a154bc2db3a7..71ac467e5104 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTDumper.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTDumper.h @@ -32,6 +32,7 @@ public: TextNodeDumper &doGetNodeDelegate() { return NodeDumper; } + void dumpInvalidDeclContext(const DeclContext *DC); void dumpLookups(const DeclContext *DC, bool DumpDecls); template <typename SpecializationDecl> diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTFwd.h b/contrib/llvm-project/clang/include/clang/AST/ASTFwd.h index 649b57113424..8823663386ea 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTFwd.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTFwd.h @@ -30,6 +30,11 @@ class OMPClause; #define GEN_CLANG_CLAUSE_CLASS #define CLAUSE_CLASS(Enum, Str, Class) class Class; #include "llvm/Frontend/OpenMP/OMP.inc" +class Attr; +#define ATTR(A) class A##Attr; +#include "clang/Basic/AttrList.inc" +class ObjCProtocolLoc; +class ConceptReference; } // end namespace clang diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTImportError.h b/contrib/llvm-project/clang/include/clang/AST/ASTImportError.h new file mode 100644 index 000000000000..728314ca0936 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/AST/ASTImportError.h @@ -0,0 +1,50 @@ +//===- ASTImportError.h - Define errors while importing AST -----*- 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 the ASTImportError class which basically defines the kind +// of error while importing AST . +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTIMPORTERROR_H +#define LLVM_CLANG_AST_ASTIMPORTERROR_H + +#include "llvm/Support/Error.h" + +namespace clang { + +class ASTImportError : public llvm::ErrorInfo<ASTImportError> { +public: + /// \brief Kind of error when importing an AST component. + enum ErrorKind { + NameConflict, /// Naming ambiguity (likely ODR violation). + UnsupportedConstruct, /// Not supported node or case. + Unknown /// Other error. + }; + + ErrorKind Error; + + static char ID; + + ASTImportError() : Error(Unknown) {} + ASTImportError(const ASTImportError &Other) : Error(Other.Error) {} + ASTImportError &operator=(const ASTImportError &Other) { + Error = Other.Error; + return *this; + } + ASTImportError(ErrorKind Error) : Error(Error) {} + + std::string toString() const; + + void log(llvm::raw_ostream &OS) const override; + std::error_code convertToErrorCode() const override; +}; + +} // namespace clang + +#endif // LLVM_CLANG_AST_ASTIMPORTERROR_H diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTImporter.h b/contrib/llvm-project/clang/include/clang/AST/ASTImporter.h index 17e673a8471a..4ffd91384657 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTImporter.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTImporter.h @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_AST_ASTIMPORTER_H #define LLVM_CLANG_AST_ASTIMPORTER_H -#include "clang/AST/APValue.h" +#include "clang/AST/ASTImportError.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExprCXX.h" @@ -27,9 +27,8 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Error.h" +#include <optional> #include <utility> namespace clang { @@ -49,33 +48,6 @@ class TagDecl; class TranslationUnitDecl; class TypeSourceInfo; - class ImportError : public llvm::ErrorInfo<ImportError> { - public: - /// \brief Kind of error when importing an AST component. - enum ErrorKind { - NameConflict, /// Naming ambiguity (likely ODR violation). - UnsupportedConstruct, /// Not supported node or case. - Unknown /// Other error. - }; - - ErrorKind Error; - - static char ID; - - ImportError() : Error(Unknown) {} - ImportError(const ImportError &Other) : Error(Other.Error) {} - ImportError &operator=(const ImportError &Other) { - Error = Other.Error; - return *this; - } - ImportError(ErrorKind Error) : Error(Error) { } - - std::string toString() const; - - void log(raw_ostream &OS) const override; - std::error_code convertToErrorCode() const override; - }; - // \brief Returns with a list of declarations started from the canonical decl // then followed by subsequent decls in the translation unit. // This gives a canonical list for each entry in the redecl chain. @@ -259,7 +231,7 @@ class TypeSourceInfo; /// imported. The same declaration may or may not be included in /// ImportedDecls. This map is updated continuously during imports and never /// cleared (like ImportedDecls). - llvm::DenseMap<Decl *, ImportError> ImportDeclErrors; + llvm::DenseMap<Decl *, ASTImportError> ImportDeclErrors; /// Mapping from the already-imported declarations in the "to" /// context to the corresponding declarations in the "from" context. @@ -286,6 +258,7 @@ class TypeSourceInfo; FoundDeclsTy findDeclsInToCtx(DeclContext *DC, DeclarationName Name); void AddToLookupTable(Decl *ToD); + llvm::Error ImportAttrs(Decl *ToD, Decl *FromD); protected: /// Can be overwritten by subclasses to implement their own import logic. @@ -332,7 +305,7 @@ class TypeSourceInfo; /// \param From Object to import. /// \return Error information (success or error). template <typename ImportT> - LLVM_NODISCARD llvm::Error importInto(ImportT &To, const ImportT &From) { + [[nodiscard]] llvm::Error importInto(ImportT &To, const ImportT &From) { auto ToOrErr = Import(From); if (ToOrErr) To = *ToOrErr; @@ -379,6 +352,9 @@ class TypeSourceInfo; return Import(const_cast<Decl *>(FromD)); } + llvm::Expected<InheritedConstructor> + Import(const InheritedConstructor &From); + /// Return the copy of the given declaration in the "to" context if /// it has already been imported from the "from" context. Otherwise return /// nullptr. @@ -392,7 +368,7 @@ class TypeSourceInfo; /// in the "to" context was imported. If it was not imported or of the wrong /// type a null value is returned. template <typename DeclT> - llvm::Optional<DeclT *> getImportedFromDecl(const DeclT *ToD) const { + std::optional<DeclT *> getImportedFromDecl(const DeclT *ToD) const { auto FromI = ImportedFromDecls.find(ToD); if (FromI == ImportedFromDecls.end()) return {}; @@ -507,7 +483,7 @@ class TypeSourceInfo; /// Import the definition of the given declaration, including all of /// the declarations it contains. - LLVM_NODISCARD llvm::Error ImportDefinition(Decl *From); + [[nodiscard]] llvm::Error ImportDefinition(Decl *From); /// Cope with a name conflict when importing a declaration into the /// given context. @@ -589,10 +565,10 @@ class TypeSourceInfo; /// Return if import of the given declaration has failed and if yes /// the kind of the problem. This gives the first error encountered with /// the node. - llvm::Optional<ImportError> getImportDeclErrorIfAny(Decl *FromD) const; + std::optional<ASTImportError> getImportDeclErrorIfAny(Decl *FromD) const; /// Mark (newly) imported declaration with error. - void setImportDeclError(Decl *From, ImportError Error); + void setImportDeclError(Decl *From, ASTImportError Error); /// Determine whether the given types are structurally /// equivalent. @@ -602,8 +578,8 @@ class TypeSourceInfo; /// Determine the index of a field in its parent record. /// F should be a field (or indirect field) declaration. /// \returns The index of the field in its parent context (starting from 0). - /// On error `None` is returned (parent context is non-record). - static llvm::Optional<unsigned> getFieldIndex(Decl *F); + /// On error `std::nullopt` is returned (parent context is non-record). + static std::optional<unsigned> getFieldIndex(Decl *F); }; } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTImporterLookupTable.h b/contrib/llvm-project/clang/include/clang/AST/ASTImporterLookupTable.h index 47dca2033839..2dbc44c5dcd4 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTImporterLookupTable.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTImporterLookupTable.h @@ -21,7 +21,6 @@ namespace clang { -class ASTContext; class NamedDecl; class DeclContext; @@ -75,6 +74,10 @@ public: // The function should be called when the old context is definitely different // from the new. void update(NamedDecl *ND, DeclContext *OldDC); + // Same as 'update' but allow if 'ND' is not in the table or the old context + // is the same as the new. + // FIXME: The old redeclaration context is not handled. + void updateForced(NamedDecl *ND, DeclContext *OldDC); using LookupResult = DeclList; LookupResult lookup(DeclContext *DC, DeclarationName Name) const; // Check if the `ND` is within the lookup table (with its current name) in diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTImporterSharedState.h b/contrib/llvm-project/clang/include/clang/AST/ASTImporterSharedState.h index 829eb1c611c3..446d7ee61ea5 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTImporterSharedState.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTImporterSharedState.h @@ -1,9 +1,8 @@ //===- ASTImporterSharedState.h - ASTImporter specific state --*- C++ -*---===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -15,11 +14,11 @@ #ifndef LLVM_CLANG_AST_ASTIMPORTERSHAREDSTATE_H #define LLVM_CLANG_AST_ASTIMPORTERSHAREDSTATE_H +#include "clang/AST/ASTImportError.h" #include "clang/AST/ASTImporterLookupTable.h" #include "clang/AST/Decl.h" #include "llvm/ADT/DenseMap.h" -// FIXME We need this because of ImportError. -#include "clang/AST/ASTImporter.h" +#include <optional> namespace clang { @@ -38,7 +37,10 @@ class ASTImporterSharedState { /// imported. The same declaration may or may not be included in /// ImportedFromDecls. This map is updated continuously during imports and /// never cleared (like ImportedFromDecls). - llvm::DenseMap<Decl *, ImportError> ImportErrors; + llvm::DenseMap<Decl *, ASTImportError> ImportErrors; + + /// Set of the newly created declarations. + llvm::DenseSet<Decl *> NewDecls; // FIXME put ImportedFromDecls here! // And from that point we can better encapsulate the lookup table. @@ -64,17 +66,21 @@ public: LookupTable->remove(ND); } - llvm::Optional<ImportError> getImportDeclErrorIfAny(Decl *ToD) const { + std::optional<ASTImportError> getImportDeclErrorIfAny(Decl *ToD) const { auto Pos = ImportErrors.find(ToD); if (Pos != ImportErrors.end()) return Pos->second; else - return Optional<ImportError>(); + return std::nullopt; } - void setImportDeclError(Decl *To, ImportError Error) { + void setImportDeclError(Decl *To, ASTImportError Error) { ImportErrors[To] = Error; } + + bool isNewDecl(const Decl *ToD) const { return NewDecls.count(ToD); } + + void markAsNewDecl(Decl *ToD) { NewDecls.insert(ToD); } }; } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTLambda.h b/contrib/llvm-project/clang/include/clang/AST/ASTLambda.h index 6fd82d6af490..646cb574847f 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTLambda.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTLambda.h @@ -35,6 +35,21 @@ inline bool isLambdaCallOperator(const DeclContext *DC) { return isLambdaCallOperator(cast<CXXMethodDecl>(DC)); } +inline bool isLambdaCallWithExplicitObjectParameter(const DeclContext *DC) { + return isLambdaCallOperator(DC) && + cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction(); +} + +inline bool isLambdaCallWithImplicitObjectParameter(const DeclContext *DC) { + return isLambdaCallOperator(DC) && + // FIXME: Checking for a null type is not great + // but lambdas with invalid captures or whose closure parameter list + // have not fully been parsed may have a call operator whose type is + // null. + !cast<CXXMethodDecl>(DC)->getType().isNull() && + !cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction(); +} + inline bool isGenericLambdaCallOperatorSpecialization(const CXXMethodDecl *MD) { if (!MD) return false; const CXXRecordDecl *LambdaClass = MD->getParent(); @@ -65,8 +80,8 @@ inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) { } inline bool isGenericLambdaCallOperatorOrStaticInvokerSpecialization( - DeclContext *DC) { - CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC); + const DeclContext *DC) { + const auto *MD = dyn_cast<CXXMethodDecl>(DC); if (!MD) return false; const CXXRecordDecl *LambdaClass = MD->getParent(); if (LambdaClass && LambdaClass->isGenericLambda()) @@ -75,7 +90,6 @@ inline bool isGenericLambdaCallOperatorOrStaticInvokerSpecialization( return false; } - // This returns the parent DeclContext ensuring that the correct // parent DeclContext is returned for Lambdas inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) { diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTNodeTraverser.h b/contrib/llvm-project/clang/include/clang/AST/ASTNodeTraverser.h index 18e7f491f222..cc8dab97f8b0 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTNodeTraverser.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTNodeTraverser.h @@ -104,7 +104,7 @@ public: Visit(Comment, Comment); // Decls within functions are visited by the body. - if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D)) { + if (!isa<FunctionDecl, ObjCMethodDecl, BlockDecl>(*D)) { if (Traversal != TK_AsIs) { if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { auto SK = CTSD->getSpecializationKind(); @@ -246,12 +246,16 @@ public: .getTypeConstraint() ->getImmediatelyDeclaredConstraint()); } else if (auto *NR = dyn_cast<concepts::NestedRequirement>(R)) { - if (!NR->isSubstitutionFailure()) + if (!NR->hasInvalidConstraint()) Visit(NR->getConstraintExpr()); } }); } + void Visit(const ConceptReference *R) { + getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(R); }); + } + void Visit(const APValue &Value, QualType Ty) { getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(Value, Ty); }); } @@ -288,6 +292,8 @@ public: Visit(C); else if (const auto *T = N.get<TemplateArgument>()) Visit(*T); + else if (const auto *CR = N.get<ConceptReference>()) + Visit(CR); } void dumpDeclContext(const DeclContext *DC) { @@ -384,18 +390,19 @@ public: } void VisitAttributedType(const AttributedType *T) { // FIXME: AttrKind - Visit(T->getModifiedType()); + if (T->getModifiedType() != T->getEquivalentType()) + Visit(T->getModifiedType()); } - void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { - Visit(T->getReplacedParameter()); + void VisitBTFTagAttributedType(const BTFTagAttributedType *T) { + Visit(T->getWrappedType()); } + void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *) {} void VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { - Visit(T->getReplacedParameter()); Visit(T->getArgumentPack()); } void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { - for (const auto &Arg : *T) + for (const auto &Arg : T->template_arguments()) Visit(Arg); } void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { @@ -419,8 +426,12 @@ public: } void VisitFunctionDecl(const FunctionDecl *D) { - if (const auto *FTSI = D->getTemplateSpecializationInfo()) + if (FunctionTemplateSpecializationInfo *FTSI = + D->getTemplateSpecializationInfo()) dumpTemplateArgumentList(*FTSI->TemplateArguments); + else if (DependentFunctionTemplateSpecializationInfo *DFTSI = + D->getDependentSpecializationInfo()) + dumpASTTemplateArgumentListInfo(DFTSI->TemplateArgumentsAsWritten); if (D->param_begin()) for (const auto *Parameter : D->parameters()) @@ -464,6 +475,10 @@ public: void VisitBindingDecl(const BindingDecl *D) { if (Traversal == TK_IgnoreUnlessSpelledInSource) return; + + if (const auto *V = D->getHoldingVar()) + Visit(V); + if (const auto *E = D->getBinding()) Visit(E); } @@ -472,6 +487,8 @@ public: Visit(D->getAsmString()); } + void VisitTopLevelStmtDecl(const TopLevelStmtDecl *D) { Visit(D->getStmt()); } + void VisitCapturedDecl(const CapturedDecl *D) { Visit(D->getBody()); } void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { @@ -565,11 +582,6 @@ public: dumpTemplateParameters(D->getTemplateParameters()); } - void VisitClassScopeFunctionSpecializationDecl( - const ClassScopeFunctionSpecializationDecl *D) { - Visit(D->getSpecialization()); - dumpASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); - } void VisitVarTemplateDecl(const VarTemplateDecl *D) { dumpTemplateDecl(D); } void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { @@ -619,7 +631,14 @@ public: Visit(D->getConstraintExpr()); } + void VisitImplicitConceptSpecializationDecl( + const ImplicitConceptSpecializationDecl *CSD) { + for (const TemplateArgument &Arg : CSD->getTemplateArguments()) + Visit(Arg); + } + void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *CSE) { + Visit(CSE->getSpecializationDecl()); if (CSE->hasExplicitTemplateArgs()) for (const auto &ArgLoc : CSE->getTemplateArgsAsWritten()->arguments()) dumpTemplateArgumentLoc(ArgLoc); @@ -631,8 +650,15 @@ public: } void VisitFriendDecl(const FriendDecl *D) { - if (!D->getFriendType()) + if (D->getFriendType()) { + // Traverse any CXXRecordDecl owned by this type, since + // it will not be in the parent context: + if (auto *ET = D->getFriendType()->getType()->getAs<ElaboratedType>()) + if (auto *TD = ET->getOwnedTagDecl()) + Visit(TD); + } else { Visit(D->getFriendDecl()); + } } void VisitObjCMethodDecl(const ObjCMethodDecl *D) { @@ -697,6 +723,12 @@ public: } } + void VisitCXXParenListInitExpr(const CXXParenListInitExpr *PLIE) { + if (auto *Filler = PLIE->getArrayFiller()) { + Visit(Filler, "array_filler"); + } + } + void VisitBlockExpr(const BlockExpr *Node) { Visit(Node->getBlockDecl()); } void VisitOpaqueValueExpr(const OpaqueValueExpr *Node) { @@ -705,8 +737,11 @@ public: } void VisitGenericSelectionExpr(const GenericSelectionExpr *E) { - Visit(E->getControllingExpr()); - Visit(E->getControllingExpr()->getType()); // FIXME: remove + if (E->isExprPredicate()) { + Visit(E->getControllingExpr()); + Visit(E->getControllingExpr()->getType()); // FIXME: remove + } else + Visit(E->getControllingType()->getType()); for (const auto Assoc : E->associations()) { Visit(Assoc); diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTStructuralEquivalence.h b/contrib/llvm-project/clang/include/clang/AST/ASTStructuralEquivalence.h index c958a16aba21..029439c8e9a3 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTStructuralEquivalence.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTStructuralEquivalence.h @@ -17,7 +17,7 @@ #include "clang/AST/DeclBase.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/Optional.h" +#include <optional> #include <queue> #include <utility> @@ -69,15 +69,19 @@ struct StructuralEquivalenceContext { /// \c true if the last diagnostic came from ToCtx. bool LastDiagFromC2 = false; + /// Whether to ignore comparing the depth of template param(TemplateTypeParm) + bool IgnoreTemplateParmDepth; + StructuralEquivalenceContext( ASTContext &FromCtx, ASTContext &ToCtx, llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls, - StructuralEquivalenceKind EqKind, - bool StrictTypeSpelling = false, bool Complain = true, - bool ErrorOnTagTypeMismatch = false) + StructuralEquivalenceKind EqKind, bool StrictTypeSpelling = false, + bool Complain = true, bool ErrorOnTagTypeMismatch = false, + bool IgnoreTemplateParmDepth = false) : FromCtx(FromCtx), ToCtx(ToCtx), NonEquivalentDecls(NonEquivalentDecls), EqKind(EqKind), StrictTypeSpelling(StrictTypeSpelling), - ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain) {} + ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain), + IgnoreTemplateParmDepth(IgnoreTemplateParmDepth) {} DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID); DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID); @@ -114,10 +118,10 @@ struct StructuralEquivalenceContext { /// /// FIXME: This is needed by ASTImporter and ASTStructureEquivalence. It /// probably makes more sense in some other common place then here. - static llvm::Optional<unsigned> + static std::optional<unsigned> findUntaggedStructOrUnionIndex(RecordDecl *Anon); - // If ErrorOnTagTypeMismatch is set, return the the error, otherwise get the + // If ErrorOnTagTypeMismatch is set, return the error, otherwise get the // relevant warning for the input error diagnostic. unsigned getApplicableDiagnostic(unsigned ErrorDiagnostic); diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTTypeTraits.h b/contrib/llvm-project/clang/include/clang/AST/ASTTypeTraits.h index 57195a9d6066..3988a15971db 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTTypeTraits.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTTypeTraits.h @@ -17,6 +17,7 @@ #include "clang/AST/ASTFwd.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/LambdaCapture.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TypeLoc.h" @@ -25,10 +26,8 @@ #include "llvm/Support/AlignOf.h" namespace llvm { - class raw_ostream; - -} +} // namespace llvm namespace clang { @@ -52,11 +51,10 @@ enum TraversalKind { class ASTNodeKind { public: /// Empty identifier. It matches nothing. - ASTNodeKind() : KindId(NKI_None) {} + constexpr ASTNodeKind() : KindId(NKI_None) {} /// Construct an identifier for T. - template <class T> - static ASTNodeKind getFromNodeKind() { + template <class T> static constexpr ASTNodeKind getFromNodeKind() { return ASTNodeKind(KindToKindId<T>::Id); } @@ -65,27 +63,33 @@ public: static ASTNodeKind getFromNode(const Decl &D); static ASTNodeKind getFromNode(const Stmt &S); static ASTNodeKind getFromNode(const Type &T); + static ASTNodeKind getFromNode(const TypeLoc &T); + static ASTNodeKind getFromNode(const LambdaCapture &L); static ASTNodeKind getFromNode(const OMPClause &C); + static ASTNodeKind getFromNode(const Attr &A); /// \} /// Returns \c true if \c this and \c Other represent the same kind. - bool isSame(ASTNodeKind Other) const { + constexpr bool isSame(ASTNodeKind Other) const { return KindId != NKI_None && KindId == Other.KindId; } /// Returns \c true only for the default \c ASTNodeKind() - bool isNone() const { return KindId == NKI_None; } + constexpr bool isNone() const { return KindId == NKI_None; } + + /// Returns \c true if \c this is a base kind of (or same as) \c Other. + bool isBaseOf(ASTNodeKind Other) const; /// Returns \c true if \c this is a base kind of (or same as) \c Other. /// \param Distance If non-null, used to return the distance between \c this /// and \c Other in the class hierarchy. - bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const; + bool isBaseOf(ASTNodeKind Other, unsigned *Distance) const; /// String representation of the kind. StringRef asStringRef() const; /// Strict weak ordering for ASTNodeKind. - bool operator<(const ASTNodeKind &Other) const { + constexpr bool operator<(const ASTNodeKind &Other) const { return KindId < Other.KindId; } @@ -119,7 +123,7 @@ public: /// Check if the given ASTNodeKind identifies a type that offers pointer /// identity. This is useful for the fast path in DynTypedNode. - bool hasPointerIdentity() const { + constexpr bool hasPointerIdentity() const { return KindId > NKI_LastKindWithoutPointerIdentity; } @@ -131,9 +135,12 @@ private: NKI_None, NKI_TemplateArgument, NKI_TemplateArgumentLoc, + NKI_LambdaCapture, NKI_TemplateName, NKI_NestedNameSpecifierLoc, NKI_QualType, +#define TYPELOC(CLASS, PARENT) NKI_##CLASS##TypeLoc, +#include "clang/AST/TypeLocNodes.def" NKI_TypeLoc, NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc, NKI_CXXBaseSpecifier, @@ -152,11 +159,20 @@ private: #define GEN_CLANG_CLAUSE_CLASS #define CLAUSE_CLASS(Enum, Str, Class) NKI_##Class, #include "llvm/Frontend/OpenMP/OMP.inc" + NKI_Attr, +#define ATTR(A) NKI_##A##Attr, +#include "clang/Basic/AttrList.inc" + NKI_ObjCProtocolLoc, + NKI_ConceptReference, NKI_NumberOfKinds }; /// Use getFromNodeKind<T>() to construct the kind. - ASTNodeKind(NodeKindId KindId) : KindId(KindId) {} + constexpr ASTNodeKind(NodeKindId KindId) : KindId(KindId) {} + + /// Returns \c true if \c Base is a base kind of (or same as) \c + /// Derived. + static bool isBaseOf(NodeKindId Base, NodeKindId Derived); /// Returns \c true if \c Base is a base kind of (or same as) \c /// Derived. @@ -192,16 +208,22 @@ private: KIND_TO_KIND_ID(CXXCtorInitializer) KIND_TO_KIND_ID(TemplateArgument) KIND_TO_KIND_ID(TemplateArgumentLoc) +KIND_TO_KIND_ID(LambdaCapture) KIND_TO_KIND_ID(TemplateName) KIND_TO_KIND_ID(NestedNameSpecifier) KIND_TO_KIND_ID(NestedNameSpecifierLoc) KIND_TO_KIND_ID(QualType) +#define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc) +#include "clang/AST/TypeLocNodes.def" KIND_TO_KIND_ID(TypeLoc) KIND_TO_KIND_ID(Decl) KIND_TO_KIND_ID(Stmt) KIND_TO_KIND_ID(Type) KIND_TO_KIND_ID(OMPClause) +KIND_TO_KIND_ID(Attr) +KIND_TO_KIND_ID(ObjCProtocolLoc) KIND_TO_KIND_ID(CXXBaseSpecifier) +KIND_TO_KIND_ID(ConceptReference) #define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl) #include "clang/AST/DeclNodes.inc" #define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED) @@ -211,6 +233,8 @@ KIND_TO_KIND_ID(CXXBaseSpecifier) #define GEN_CLANG_CLAUSE_CLASS #define CLAUSE_CLASS(Enum, Str, Class) KIND_TO_KIND_ID(Class) #include "llvm/Frontend/OpenMP/OMP.inc" +#define ATTR(A) KIND_TO_KIND_ID(A##Attr) +#include "clang/Basic/AttrList.inc" #undef KIND_TO_KIND_ID inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) { @@ -299,7 +323,7 @@ public: return getUnchecked<QualType>().getAsOpaquePtr() < Other.getUnchecked<QualType>().getAsOpaquePtr(); - if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) { + if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(NodeKind)) { auto TLA = getUnchecked<TypeLoc>(); auto TLB = Other.getUnchecked<TypeLoc>(); return std::make_pair(TLA.getType().getAsOpaquePtr(), @@ -331,7 +355,7 @@ public: if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind)) return getUnchecked<QualType>() == Other.getUnchecked<QualType>(); - if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) + if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(NodeKind)) return getUnchecked<TypeLoc>() == Other.getUnchecked<TypeLoc>(); if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(NodeKind)) @@ -360,7 +384,7 @@ public: } static unsigned getHashValue(const DynTypedNode &Val) { // FIXME: Add hashing support for the remaining types. - if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(Val.NodeKind)) { + if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(Val.NodeKind)) { auto TL = Val.getUnchecked<TypeLoc>(); return llvm::hash_combine(TL.getType().getAsOpaquePtr(), TL.getOpaqueData()); @@ -450,6 +474,29 @@ private: } }; + /// Converter that stores nodes by value. It must be possible to dynamically + /// cast the stored node within a type hierarchy without breaking (especially + /// through slicing). + template <typename T, typename BaseT, + typename = std::enable_if_t<(sizeof(T) == sizeof(BaseT))>> + struct DynCastValueConverter { + static const T *get(ASTNodeKind NodeKind, const void *Storage) { + if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)) + return &getUnchecked(NodeKind, Storage); + return nullptr; + } + static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) { + assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)); + return *static_cast<const T *>(reinterpret_cast<const BaseT *>(Storage)); + } + static DynTypedNode create(const T &Node) { + DynTypedNode Result; + Result.NodeKind = ASTNodeKind::getFromNode(Node); + new (&Result.Storage) T(Node); + return Result; + } + }; + ASTNodeKind NodeKind; /// Stores the data of the node. @@ -462,7 +509,7 @@ private: /// have storage or unique pointers and thus need to be stored by value. llvm::AlignedCharArrayUnion<const void *, TemplateArgument, TemplateArgumentLoc, NestedNameSpecifierLoc, - QualType, TypeLoc> + QualType, TypeLoc, ObjCProtocolLoc> Storage; }; @@ -486,6 +533,11 @@ struct DynTypedNode::BaseConverter< T, std::enable_if_t<std::is_base_of<OMPClause, T>::value>> : public DynCastPtrConverter<T, OMPClause> {}; +template <typename T> +struct DynTypedNode::BaseConverter< + T, std::enable_if_t<std::is_base_of<Attr, T>::value>> + : public DynCastPtrConverter<T, Attr> {}; + template <> struct DynTypedNode::BaseConverter< NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {}; @@ -503,6 +555,10 @@ struct DynTypedNode::BaseConverter<TemplateArgumentLoc, void> : public ValueConverter<TemplateArgumentLoc> {}; template <> +struct DynTypedNode::BaseConverter<LambdaCapture, void> + : public ValueConverter<LambdaCapture> {}; + +template <> struct DynTypedNode::BaseConverter< TemplateName, void> : public ValueConverter<TemplateName> {}; @@ -515,14 +571,23 @@ template <> struct DynTypedNode::BaseConverter<QualType, void> : public ValueConverter<QualType> {}; -template <> +template <typename T> struct DynTypedNode::BaseConverter< - TypeLoc, void> : public ValueConverter<TypeLoc> {}; + T, std::enable_if_t<std::is_base_of<TypeLoc, T>::value>> + : public DynCastValueConverter<T, TypeLoc> {}; template <> struct DynTypedNode::BaseConverter<CXXBaseSpecifier, void> : public PtrConverter<CXXBaseSpecifier> {}; +template <> +struct DynTypedNode::BaseConverter<ObjCProtocolLoc, void> + : public ValueConverter<ObjCProtocolLoc> {}; + +template <> +struct DynTypedNode::BaseConverter<ConceptReference, void> + : public PtrConverter<ConceptReference> {}; + // The only operation we allow on unsupported types is \c get. // This allows to conveniently use \c DynTypedNode when having an arbitrary // AST node that is not supported, but prevents misuse - a user cannot create diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTUnresolvedSet.h b/contrib/llvm-project/clang/include/clang/AST/ASTUnresolvedSet.h index 8d2b23b3539a..398ffb188c95 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTUnresolvedSet.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTUnresolvedSet.h @@ -69,7 +69,12 @@ public: return false; } - void erase(unsigned I) { Decls[I] = Decls.pop_back_val(); } + void erase(unsigned I) { + if (I == Decls.size() - 1) + Decls.pop_back(); + else + Decls[I] = Decls.pop_back_val(); + } void clear() { Decls.clear(); } diff --git a/contrib/llvm-project/clang/include/clang/AST/AbstractBasicReader.h b/contrib/llvm-project/clang/include/clang/AST/AbstractBasicReader.h index 5505d661b44e..1f2797cc7014 100644 --- a/contrib/llvm-project/clang/include/clang/AST/AbstractBasicReader.h +++ b/contrib/llvm-project/clang/include/clang/AST/AbstractBasicReader.h @@ -6,22 +6,22 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_AST_ABSTRACTBASICREADER_H -#define CLANG_AST_ABSTRACTBASICREADER_H +#ifndef LLVM_CLANG_AST_ABSTRACTBASICREADER_H +#define LLVM_CLANG_AST_ABSTRACTBASICREADER_H #include "clang/AST/DeclTemplate.h" +#include <optional> namespace clang { namespace serialization { template <class T> -inline T makeNullableFromOptional(const Optional<T> &value) { +inline T makeNullableFromOptional(const std::optional<T> &value) { return (value ? *value : T()); } -template <class T> -inline T *makePointerFromOptional(Optional<T *> value) { - return (value ? *value : nullptr); +template <class T> inline T *makePointerFromOptional(std::optional<T *> value) { + return value.value_or(nullptr); } // PropertyReader is a class concept that requires the following method: @@ -49,7 +49,7 @@ inline T *makePointerFromOptional(Optional<T *> value) { // type-specific readers for all the enum types. // // template <class ValueType> -// Optional<ValueType> writeOptional(); +// std::optional<ValueType> writeOptional(); // // Reads an optional value from the current property. // @@ -157,7 +157,7 @@ public: } template <class T, class... Args> - llvm::Optional<T> readOptional(Args &&...args) { + std::optional<T> readOptional(Args &&...args) { return UnpackOptionalValue<T>::unpack( ReadDispatcher<T>::read(asImpl(), std::forward<Args>(args)...)); } @@ -190,7 +190,8 @@ public: APValue::LValuePathSerializationHelper readLValuePathSerializationHelper( SmallVectorImpl<APValue::LValuePathEntry> &path) { - auto elemTy = asImpl().readQualType(); + auto origTy = asImpl().readQualType(); + auto elemTy = origTy; unsigned pathLength = asImpl().readUInt32(); for (unsigned i = 0; i < pathLength; ++i) { if (elemTy->template getAs<RecordType>()) { @@ -208,7 +209,7 @@ public: APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32())); } } - return APValue::LValuePathSerializationHelper(path, elemTy); + return APValue::LValuePathSerializationHelper(path, origTy); } Qualifiers readQualifiers() { diff --git a/contrib/llvm-project/clang/include/clang/AST/AbstractBasicWriter.h b/contrib/llvm-project/clang/include/clang/AST/AbstractBasicWriter.h index 75aef734ba9b..07afa388de2c 100644 --- a/contrib/llvm-project/clang/include/clang/AST/AbstractBasicWriter.h +++ b/contrib/llvm-project/clang/include/clang/AST/AbstractBasicWriter.h @@ -6,25 +6,23 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_AST_ABSTRACTBASICWRITER_H -#define CLANG_AST_ABSTRACTBASICWRITER_H +#ifndef LLVM_CLANG_AST_ABSTRACTBASICWRITER_H +#define LLVM_CLANG_AST_ABSTRACTBASICWRITER_H #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" +#include <optional> namespace clang { namespace serialization { template <class T> -inline llvm::Optional<T> makeOptionalFromNullable(const T &value) { - return (value.isNull() - ? llvm::Optional<T>() - : llvm::Optional<T>(value)); +inline std::optional<T> makeOptionalFromNullable(const T &value) { + return (value.isNull() ? std::optional<T>() : std::optional<T>(value)); } -template <class T> -inline llvm::Optional<T*> makeOptionalFromPointer(T *value) { - return (value ? llvm::Optional<T*>(value) : llvm::Optional<T*>()); +template <class T> inline std::optional<T *> makeOptionalFromPointer(T *value) { + return (value ? std::optional<T *>(value) : std::optional<T *>()); } // PropertyWriter is a class concept that requires the following method: @@ -51,7 +49,7 @@ inline llvm::Optional<T*> makeOptionalFromPointer(T *value) { // type-specific writers for all the enum types. // // template <class ValueType> -// void writeOptional(Optional<ValueType> value); +// void writeOptional(std::optional<ValueType> value); // // Writes an optional value as the current property. // @@ -148,8 +146,7 @@ public: } } - template <class T> - void writeOptional(llvm::Optional<T> value) { + template <class T> void writeOptional(std::optional<T> value) { WriteDispatcher<T>::write(asImpl(), PackOptionalValue<T>::pack(value)); } diff --git a/contrib/llvm-project/clang/include/clang/AST/AbstractTypeReader.h b/contrib/llvm-project/clang/include/clang/AST/AbstractTypeReader.h index 9fea7b26f678..e44bbf61c0ed 100644 --- a/contrib/llvm-project/clang/include/clang/AST/AbstractTypeReader.h +++ b/contrib/llvm-project/clang/include/clang/AST/AbstractTypeReader.h @@ -6,11 +6,12 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_AST_ABSTRACTTYPEREADER_H -#define CLANG_AST_ABSTRACTTYPEREADER_H +#ifndef LLVM_CLANG_AST_ABSTRACTTYPEREADER_H +#define LLVM_CLANG_AST_ABSTRACTTYPEREADER_H -#include "clang/AST/Type.h" #include "clang/AST/AbstractBasicReader.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Type.h" namespace clang { namespace serialization { diff --git a/contrib/llvm-project/clang/include/clang/AST/AbstractTypeWriter.h b/contrib/llvm-project/clang/include/clang/AST/AbstractTypeWriter.h index a63cb0be099d..62006ef0f26e 100644 --- a/contrib/llvm-project/clang/include/clang/AST/AbstractTypeWriter.h +++ b/contrib/llvm-project/clang/include/clang/AST/AbstractTypeWriter.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_AST_ABSTRACTTYPEWRITER_H -#define CLANG_AST_ABSTRACTTYPEWRITER_H +#ifndef LLVM_CLANG_AST_ABSTRACTTYPEWRITER_H +#define LLVM_CLANG_AST_ABSTRACTTYPEWRITER_H #include "clang/AST/Type.h" #include "clang/AST/AbstractBasicWriter.h" diff --git a/contrib/llvm-project/clang/include/clang/AST/Attr.h b/contrib/llvm-project/clang/include/clang/AST/Attr.h index dbfecc125049..8e9b7ad8b468 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Attr.h +++ b/contrib/llvm-project/clang/include/clang/AST/Attr.h @@ -19,12 +19,13 @@ #include "clang/AST/Type.h" #include "clang/Basic/AttrKinds.h" #include "clang/Basic/AttributeCommonInfo.h" -#include "clang/Basic/LangOptions.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/Sanitizers.h" #include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/StringSwitch.h" +#include "llvm/Frontend/HLSL/HLSLResource.h" +#include "llvm/Support/CodeGen.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" @@ -34,28 +35,29 @@ namespace clang { class ASTContext; class AttributeCommonInfo; -class IdentifierInfo; -class ObjCInterfaceDecl; -class Expr; -class QualType; class FunctionDecl; -class TypeSourceInfo; class OMPTraitInfo; /// Attr - This represents one attribute. class Attr : public AttributeCommonInfo { private: + LLVM_PREFERRED_TYPE(attr::Kind) unsigned AttrKind : 16; protected: /// An index into the spelling list of an /// attribute defined in Attr.td file. + LLVM_PREFERRED_TYPE(bool) unsigned Inherited : 1; + LLVM_PREFERRED_TYPE(bool) unsigned IsPackExpansion : 1; + LLVM_PREFERRED_TYPE(bool) unsigned Implicit : 1; // FIXME: These are properties of the attribute kind, not state for this // instance of the attribute. + LLVM_PREFERRED_TYPE(bool) unsigned IsLateParsed : 1; + LLVM_PREFERRED_TYPE(bool) unsigned InheritEvenIfAlreadyPresent : 1; void *operator new(size_t bytes) noexcept { @@ -109,6 +111,8 @@ public: // Pretty print this attribute. void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const; + + static StringRef getDocumentation(attr::Kind); }; class TypeAttr : public Attr { @@ -193,6 +197,22 @@ public: } }; +class HLSLAnnotationAttr : public InheritableAttr { +protected: + HLSLAnnotationAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, + attr::Kind AK, bool IsLateParsed, + bool InheritEvenIfAlreadyPresent) + : InheritableAttr(Context, CommonInfo, AK, IsLateParsed, + InheritEvenIfAlreadyPresent) {} + +public: + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() >= attr::FirstHLSLAnnotationAttr && + A->getKind() <= attr::LastHLSLAnnotationAttr; + } +}; + /// A parameter attribute which changes the argument-passing ABI rule /// for the parameter. class ParameterABIAttr : public InheritableParamAttr { @@ -230,7 +250,9 @@ public: class ParamIdx { // Idx is exposed only via accessors that specify specific encodings. unsigned Idx : 30; + LLVM_PREFERRED_TYPE(bool) unsigned HasThis : 1; + LLVM_PREFERRED_TYPE(bool) unsigned IsValid : 1; void assertComparable(const ParamIdx &I) const { @@ -350,30 +372,11 @@ public: static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType), "ParamIdx does not fit its serialization type"); -/// Contains information gathered from parsing the contents of TargetAttr. -struct ParsedTargetAttr { - std::vector<std::string> Features; - StringRef Architecture; - StringRef Tune; - StringRef BranchProtection; - bool DuplicateArchitecture = false; - bool DuplicateTune = false; - bool operator ==(const ParsedTargetAttr &Other) const { - return DuplicateArchitecture == Other.DuplicateArchitecture && - DuplicateTune == Other.DuplicateTune && - Architecture == Other.Architecture && - Tune == Other.Tune && - BranchProtection == Other.BranchProtection && - Features == Other.Features; - } -}; - #include "clang/AST/Attrs.inc" inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, const Attr *At) { - DB.AddTaggedVal(reinterpret_cast<intptr_t>(At), - DiagnosticsEngine::ak_attr); + DB.AddTaggedVal(reinterpret_cast<uint64_t>(At), DiagnosticsEngine::ak_attr); return DB; } } // end namespace clang diff --git a/contrib/llvm-project/clang/include/clang/AST/AttrIterator.h b/contrib/llvm-project/clang/include/clang/AST/AttrIterator.h index 78ce9314a2bb..66571e1cf0b8 100644 --- a/contrib/llvm-project/clang/include/clang/AST/AttrIterator.h +++ b/contrib/llvm-project/clang/include/clang/AST/AttrIterator.h @@ -22,7 +22,6 @@ namespace clang { -class ASTContext; class Attr; /// AttrVec - A vector of Attr, which is how they are stored on the AST. diff --git a/contrib/llvm-project/clang/include/clang/AST/BuiltinTypes.def b/contrib/llvm-project/clang/include/clang/AST/BuiltinTypes.def index 039765dfdfea..c04f6f6f1271 100644 --- a/contrib/llvm-project/clang/include/clang/AST/BuiltinTypes.def +++ b/contrib/llvm-project/clang/include/clang/AST/BuiltinTypes.def @@ -218,6 +218,9 @@ FLOATING_TYPE(BFloat16, BFloat16Ty) // '__float128' FLOATING_TYPE(Float128, Float128Ty) +// '__ibm128' +FLOATING_TYPE(Ibm128, Ibm128Ty) + //===- Language-specific types --------------------------------------------===// // This is the type of C++0x 'nullptr'. diff --git a/contrib/llvm-project/clang/include/clang/AST/CXXInheritance.h b/contrib/llvm-project/clang/include/clang/AST/CXXInheritance.h index 946b9e318baa..bbef01843e0b 100644 --- a/contrib/llvm-project/clang/include/clang/AST/CXXInheritance.h +++ b/contrib/llvm-project/clang/include/clang/AST/CXXInheritance.h @@ -20,7 +20,6 @@ #include "clang/AST/TypeOrdering.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" @@ -131,6 +130,7 @@ class CXXBasePaths { /// class subobjects for that class type. The key of the map is /// the cv-unqualified canonical type of the base class subobject. struct IsVirtBaseAndNumberNonVirtBases { + LLVM_PREFERRED_TYPE(bool) unsigned IsVirtBase : 1; unsigned NumberOfNonVirtBases : 31; }; @@ -315,7 +315,7 @@ public: /// virtual function; in abstract classes, the final overrider for at /// least one virtual function is a pure virtual function. Due to /// multiple, virtual inheritance, it is possible for a class to have -/// more than one final overrider. Athough this is an error (per C++ +/// more than one final overrider. Although this is an error (per C++ /// [class.virtual]p2), it is not considered an error here: the final /// overrider map can represent multiple final overriders for a /// method, and it is up to the client to determine whether they are diff --git a/contrib/llvm-project/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def b/contrib/llvm-project/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def index 9b270682f8cf..cdf0804680ad 100644 --- a/contrib/llvm-project/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def +++ b/contrib/llvm-project/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def @@ -112,6 +112,9 @@ FIELD(HasVariantMembers, 1, NO_MERGE) /// True if there no non-field members declared by the user. FIELD(HasOnlyCMembers, 1, NO_MERGE) +/// True if there is an '__init' method defined by the user. +FIELD(HasInitMethod, 1, NO_MERGE) + /// True if any field has an in-class initializer, including those /// within anonymous unions or structs. FIELD(HasInClassInitializer, 1, NO_MERGE) diff --git a/contrib/llvm-project/clang/include/clang/AST/CanonicalType.h b/contrib/llvm-project/clang/include/clang/AST/CanonicalType.h index 15d7e9efc26a..dde08f0394c9 100644 --- a/contrib/llvm-project/clang/include/clang/AST/CanonicalType.h +++ b/contrib/llvm-project/clang/include/clang/AST/CanonicalType.h @@ -305,7 +305,6 @@ public: LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType) @@ -529,7 +528,7 @@ struct CanProxyAdaptor<FunctionProtoType> template<> struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnmodifiedType) }; template<> diff --git a/contrib/llvm-project/clang/include/clang/AST/CharUnits.h b/contrib/llvm-project/clang/include/clang/AST/CharUnits.h index f14d3abf71e5..c06354451dfb 100644 --- a/contrib/llvm-project/clang/include/clang/AST/CharUnits.h +++ b/contrib/llvm-project/clang/include/clang/AST/CharUnits.h @@ -64,6 +64,12 @@ namespace clang { return CharUnits(Quantity); } + /// fromQuantity - Construct a CharUnits quantity from an llvm::Align + /// quantity. + static CharUnits fromQuantity(llvm::Align Quantity) { + return CharUnits(Quantity.value()); + } + // Compound assignment. CharUnits& operator+= (const CharUnits &Other) { Quantity += Other.Quantity; @@ -182,6 +188,13 @@ namespace clang { /// Beware llvm::Align assumes power of two 8-bit bytes. llvm::Align getAsAlign() const { return llvm::Align(Quantity); } + /// getAsMaybeAlign - Returns Quantity as a valid llvm::Align or + /// std::nullopt, Beware llvm::MaybeAlign assumes power of two 8-bit + /// bytes. + llvm::MaybeAlign getAsMaybeAlign() const { + return llvm::MaybeAlign(Quantity); + } + /// alignTo - Returns the next integer (mod 2**64) that is /// greater than or equal to this quantity and is a multiple of \p Align. /// Align must be non-zero. diff --git a/contrib/llvm-project/clang/include/clang/AST/Comment.h b/contrib/llvm-project/clang/include/clang/AST/Comment.h index 54a4b0a9cfe6..dd9906727293 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Comment.h +++ b/contrib/llvm-project/clang/include/clang/AST/Comment.h @@ -27,6 +27,8 @@ class TemplateParameterList; namespace comments { class FullComment; +enum class InlineCommandRenderKind; +enum class ParamCommandPassDirection; /// Describes the syntax that was used in a documentation command. /// @@ -47,6 +49,17 @@ enum CommandMarkerKind { CMK_At = 1 }; +enum class CommentKind { + None = 0, +#define COMMENT(CLASS, PARENT) CLASS, +#define COMMENT_RANGE(BASE, FIRST, LAST) \ + First##BASE##Constant = FIRST, Last##BASE##Constant = LAST, +#define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \ + First##BASE##Constant = FIRST, Last##BASE##Constant = LAST +#define ABSTRACT_COMMENT(COMMENT) +#include "clang/AST/CommentNodes.inc" +}; + /// Any part of the comment. /// Abstract class. class Comment { @@ -61,6 +74,7 @@ protected: friend class Comment; /// Type of this AST node. + LLVM_PREFERRED_TYPE(CommentKind) unsigned Kind : 8; }; enum { NumCommentBits = 8 }; @@ -68,10 +82,12 @@ protected: class InlineContentCommentBitfields { friend class InlineContentComment; + LLVM_PREFERRED_TYPE(CommentBitfields) unsigned : NumCommentBits; /// True if there is a newline after this inline content node. /// (There is no separate AST node for a newline.) + LLVM_PREFERRED_TYPE(bool) unsigned HasTrailingNewline : 1; }; enum { NumInlineContentCommentBits = NumCommentBits + 1 }; @@ -79,12 +95,15 @@ protected: class TextCommentBitfields { friend class TextComment; + LLVM_PREFERRED_TYPE(InlineContentCommentBitfields) unsigned : NumInlineContentCommentBits; /// True if \c IsWhitespace field contains a valid value. + LLVM_PREFERRED_TYPE(bool) mutable unsigned IsWhitespaceValid : 1; /// True if this comment AST node contains only whitespace. + LLVM_PREFERRED_TYPE(bool) mutable unsigned IsWhitespace : 1; }; enum { NumTextCommentBits = NumInlineContentCommentBits + 2 }; @@ -92,10 +111,13 @@ protected: class InlineCommandCommentBitfields { friend class InlineCommandComment; + LLVM_PREFERRED_TYPE(InlineContentCommentBitfields) unsigned : NumInlineContentCommentBits; + LLVM_PREFERRED_TYPE(InlineCommandRenderKind) unsigned RenderKind : 3; + LLVM_PREFERRED_TYPE(CommandTraits::KnownCommandIDs) unsigned CommandID : CommandInfo::NumCommandIDBits; }; enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 3 + @@ -104,9 +126,11 @@ protected: class HTMLTagCommentBitfields { friend class HTMLTagComment; + LLVM_PREFERRED_TYPE(InlineContentCommentBitfields) unsigned : NumInlineContentCommentBits; /// True if we found that this tag is malformed in some way. + LLVM_PREFERRED_TYPE(bool) unsigned IsMalformed : 1; }; enum { NumHTMLTagCommentBits = NumInlineContentCommentBits + 1 }; @@ -114,10 +138,12 @@ protected: class HTMLStartTagCommentBitfields { friend class HTMLStartTagComment; + LLVM_PREFERRED_TYPE(HTMLTagCommentBitfields) unsigned : NumHTMLTagCommentBits; /// True if this tag is self-closing (e. g., <br />). This is based on tag /// spelling in comment (plain <br> would not set this flag). + LLVM_PREFERRED_TYPE(bool) unsigned IsSelfClosing : 1; }; enum { NumHTMLStartTagCommentBits = NumHTMLTagCommentBits + 1 }; @@ -125,12 +151,15 @@ protected: class ParagraphCommentBitfields { friend class ParagraphComment; + LLVM_PREFERRED_TYPE(CommentBitfields) unsigned : NumCommentBits; /// True if \c IsWhitespace field contains a valid value. + LLVM_PREFERRED_TYPE(bool) mutable unsigned IsWhitespaceValid : 1; /// True if this comment AST node contains only whitespace. + LLVM_PREFERRED_TYPE(bool) mutable unsigned IsWhitespace : 1; }; enum { NumParagraphCommentBits = NumCommentBits + 2 }; @@ -138,12 +167,15 @@ protected: class BlockCommandCommentBitfields { friend class BlockCommandComment; + LLVM_PREFERRED_TYPE(CommentBitfields) unsigned : NumCommentBits; + LLVM_PREFERRED_TYPE(CommandTraits::KnownCommandIDs) unsigned CommandID : CommandInfo::NumCommandIDBits; /// Describes the syntax that was used in a documentation command. /// Contains values from CommandMarkerKind enum. + LLVM_PREFERRED_TYPE(CommandMarkerKind) unsigned CommandMarker : 1; }; enum { NumBlockCommandCommentBits = NumCommentBits + @@ -152,12 +184,15 @@ protected: class ParamCommandCommentBitfields { friend class ParamCommandComment; + LLVM_PREFERRED_TYPE(BlockCommandCommentBitfields) unsigned : NumBlockCommandCommentBits; - /// Parameter passing direction, see ParamCommandComment::PassDirection. + /// Parameter passing direction. + LLVM_PREFERRED_TYPE(ParamCommandPassDirection) unsigned Direction : 2; /// True if direction was specified explicitly in the comment. + LLVM_PREFERRED_TYPE(bool) unsigned IsDirectionExplicit : 1; }; enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 }; @@ -183,22 +218,16 @@ protected: } public: - enum CommentKind { - NoCommentKind = 0, -#define COMMENT(CLASS, PARENT) CLASS##Kind, -#define COMMENT_RANGE(BASE, FIRST, LAST) \ - First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind, -#define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \ - First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind -#define ABSTRACT_COMMENT(COMMENT) -#include "clang/AST/CommentNodes.inc" + struct Argument { + SourceRange Range; + StringRef Text; }; Comment(CommentKind K, SourceLocation LocBegin, SourceLocation LocEnd) : Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) { - CommentBits.Kind = K; + CommentBits.Kind = llvm::to_underlying(K); } CommentKind getCommentKind() const { @@ -244,8 +273,9 @@ protected: public: static bool classof(const Comment *C) { - return C->getCommentKind() >= FirstInlineContentCommentConstant && - C->getCommentKind() <= LastInlineContentCommentConstant; + return C->getCommentKind() >= + CommentKind::FirstInlineContentCommentConstant && + C->getCommentKind() <= CommentKind::LastInlineContentCommentConstant; } void addTrailingNewline() { @@ -262,16 +292,14 @@ class TextComment : public InlineContentComment { StringRef Text; public: - TextComment(SourceLocation LocBegin, - SourceLocation LocEnd, - StringRef Text) : - InlineContentComment(TextCommentKind, LocBegin, LocEnd), - Text(Text) { + TextComment(SourceLocation LocBegin, SourceLocation LocEnd, StringRef Text) + : InlineContentComment(CommentKind::TextComment, LocBegin, LocEnd), + Text(Text) { TextCommentBits.IsWhitespaceValid = false; } static bool classof(const Comment *C) { - return C->getCommentKind() == TextCommentKind; + return C->getCommentKind() == CommentKind::TextComment; } child_iterator child_begin() const { return nullptr; } @@ -293,44 +321,35 @@ private: bool isWhitespaceNoCache() const; }; +/// The most appropriate rendering mode for this command, chosen on command +/// semantics in Doxygen. +enum class InlineCommandRenderKind { + Normal, + Bold, + Monospaced, + Emphasized, + Anchor +}; + /// A command with word-like arguments that is considered inline content. class InlineCommandComment : public InlineContentComment { -public: - struct Argument { - SourceRange Range; - StringRef Text; - - Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { } - }; - - /// The most appropriate rendering mode for this command, chosen on command - /// semantics in Doxygen. - enum RenderKind { - RenderNormal, - RenderBold, - RenderMonospaced, - RenderEmphasized, - RenderAnchor - }; - protected: /// Command arguments. ArrayRef<Argument> Args; public: - InlineCommandComment(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - RenderKind RK, - ArrayRef<Argument> Args) : - InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd), - Args(Args) { - InlineCommandCommentBits.RenderKind = RK; + InlineCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, + unsigned CommandID, InlineCommandRenderKind RK, + ArrayRef<Argument> Args) + : InlineContentComment(CommentKind::InlineCommandComment, LocBegin, + LocEnd), + Args(Args) { + InlineCommandCommentBits.RenderKind = llvm::to_underlying(RK); InlineCommandCommentBits.CommandID = CommandID; } static bool classof(const Comment *C) { - return C->getCommentKind() == InlineCommandCommentKind; + return C->getCommentKind() == CommentKind::InlineCommandComment; } child_iterator child_begin() const { return nullptr; } @@ -349,8 +368,9 @@ public: return SourceRange(getBeginLoc().getLocWithOffset(-1), getEndLoc()); } - RenderKind getRenderKind() const { - return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind); + InlineCommandRenderKind getRenderKind() const { + return static_cast<InlineCommandRenderKind>( + InlineCommandCommentBits.RenderKind); } unsigned getNumArgs() const { @@ -388,8 +408,8 @@ protected: public: static bool classof(const Comment *C) { - return C->getCommentKind() >= FirstHTMLTagCommentConstant && - C->getCommentKind() <= LastHTMLTagCommentConstant; + return C->getCommentKind() >= CommentKind::FirstHTMLTagCommentConstant && + C->getCommentKind() <= CommentKind::LastHTMLTagCommentConstant; } StringRef getTagName() const LLVM_READONLY { return TagName; } @@ -424,19 +444,13 @@ public: Attribute() { } - Attribute(SourceLocation NameLocBegin, StringRef Name) : - NameLocBegin(NameLocBegin), Name(Name), - EqualsLoc(SourceLocation()), - ValueRange(SourceRange()), Value(StringRef()) - { } + Attribute(SourceLocation NameLocBegin, StringRef Name) + : NameLocBegin(NameLocBegin), Name(Name), EqualsLoc(SourceLocation()) {} Attribute(SourceLocation NameLocBegin, StringRef Name, - SourceLocation EqualsLoc, - SourceRange ValueRange, StringRef Value) : - NameLocBegin(NameLocBegin), Name(Name), - EqualsLoc(EqualsLoc), - ValueRange(ValueRange), Value(Value) - { } + SourceLocation EqualsLoc, SourceRange ValueRange, StringRef Value) + : NameLocBegin(NameLocBegin), Name(Name), EqualsLoc(EqualsLoc), + ValueRange(ValueRange), Value(Value) {} SourceLocation getNameLocEnd() const { return NameLocBegin.getLocWithOffset(Name.size()); @@ -451,18 +465,16 @@ private: ArrayRef<Attribute> Attributes; public: - HTMLStartTagComment(SourceLocation LocBegin, - StringRef TagName) : - HTMLTagComment(HTMLStartTagCommentKind, - LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()), - TagName, - LocBegin.getLocWithOffset(1), - LocBegin.getLocWithOffset(1 + TagName.size())) { + HTMLStartTagComment(SourceLocation LocBegin, StringRef TagName) + : HTMLTagComment(CommentKind::HTMLStartTagComment, LocBegin, + LocBegin.getLocWithOffset(1 + TagName.size()), TagName, + LocBegin.getLocWithOffset(1), + LocBegin.getLocWithOffset(1 + TagName.size())) { HTMLStartTagCommentBits.IsSelfClosing = false; } static bool classof(const Comment *C) { - return C->getCommentKind() == HTMLStartTagCommentKind; + return C->getCommentKind() == CommentKind::HTMLStartTagComment; } child_iterator child_begin() const { return nullptr; } @@ -506,18 +518,14 @@ public: /// A closing HTML tag. class HTMLEndTagComment : public HTMLTagComment { public: - HTMLEndTagComment(SourceLocation LocBegin, - SourceLocation LocEnd, - StringRef TagName) : - HTMLTagComment(HTMLEndTagCommentKind, - LocBegin, LocEnd, - TagName, - LocBegin.getLocWithOffset(2), - LocBegin.getLocWithOffset(2 + TagName.size())) - { } + HTMLEndTagComment(SourceLocation LocBegin, SourceLocation LocEnd, + StringRef TagName) + : HTMLTagComment(CommentKind::HTMLEndTagComment, LocBegin, LocEnd, + TagName, LocBegin.getLocWithOffset(2), + LocBegin.getLocWithOffset(2 + TagName.size())) {} static bool classof(const Comment *C) { - return C->getCommentKind() == HTMLEndTagCommentKind; + return C->getCommentKind() == CommentKind::HTMLEndTagComment; } child_iterator child_begin() const { return nullptr; } @@ -537,8 +545,9 @@ protected: public: static bool classof(const Comment *C) { - return C->getCommentKind() >= FirstBlockContentCommentConstant && - C->getCommentKind() <= LastBlockContentCommentConstant; + return C->getCommentKind() >= + CommentKind::FirstBlockContentCommentConstant && + C->getCommentKind() <= CommentKind::LastBlockContentCommentConstant; } }; @@ -547,11 +556,10 @@ class ParagraphComment : public BlockContentComment { ArrayRef<InlineContentComment *> Content; public: - ParagraphComment(ArrayRef<InlineContentComment *> Content) : - BlockContentComment(ParagraphCommentKind, - SourceLocation(), - SourceLocation()), - Content(Content) { + ParagraphComment(ArrayRef<InlineContentComment *> Content) + : BlockContentComment(CommentKind::ParagraphComment, SourceLocation(), + SourceLocation()), + Content(Content) { if (Content.empty()) { ParagraphCommentBits.IsWhitespace = true; ParagraphCommentBits.IsWhitespaceValid = true; @@ -566,7 +574,7 @@ public: } static bool classof(const Comment *C) { - return C->getCommentKind() == ParagraphCommentKind; + return C->getCommentKind() == CommentKind::ParagraphComment; } child_iterator child_begin() const { @@ -594,15 +602,6 @@ private: /// arguments depends on command name) and a paragraph as an argument /// (e. g., \\brief). class BlockCommandComment : public BlockContentComment { -public: - struct Argument { - SourceRange Range; - StringRef Text; - - Argument() { } - Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { } - }; - protected: /// Word-like arguments. ArrayRef<Argument> Args; @@ -623,20 +622,19 @@ protected: } public: - BlockCommandComment(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - CommandMarkerKind CommandMarker) : - BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd), - Paragraph(nullptr) { + BlockCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, + unsigned CommandID, CommandMarkerKind CommandMarker) + : BlockContentComment(CommentKind::BlockCommandComment, LocBegin, LocEnd), + Paragraph(nullptr) { setLocation(getCommandNameBeginLoc()); BlockCommandCommentBits.CommandID = CommandID; BlockCommandCommentBits.CommandMarker = CommandMarker; } static bool classof(const Comment *C) { - return C->getCommentKind() >= FirstBlockCommandCommentConstant && - C->getCommentKind() <= LastBlockCommandCommentConstant; + return C->getCommentKind() >= + CommentKind::FirstBlockCommandCommentConstant && + C->getCommentKind() <= CommentKind::LastBlockCommandCommentConstant; } child_iterator child_begin() const { @@ -707,6 +705,8 @@ public: } }; +enum class ParamCommandPassDirection { In, Out, InOut }; + /// Doxygen \\param command. class ParamCommandComment : public BlockCommandComment { private: @@ -719,39 +719,33 @@ public: VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U }; - ParamCommandComment(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - CommandMarkerKind CommandMarker) : - BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, - CommandID, CommandMarker), - ParamIndex(InvalidParamIndex) { - ParamCommandCommentBits.Direction = In; + ParamCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, + unsigned CommandID, CommandMarkerKind CommandMarker) + : BlockCommandComment(CommentKind::ParamCommandComment, LocBegin, LocEnd, + CommandID, CommandMarker), + ParamIndex(InvalidParamIndex) { + ParamCommandCommentBits.Direction = + llvm::to_underlying(ParamCommandPassDirection::In); ParamCommandCommentBits.IsDirectionExplicit = false; } static bool classof(const Comment *C) { - return C->getCommentKind() == ParamCommandCommentKind; + return C->getCommentKind() == CommentKind::ParamCommandComment; } - enum PassDirection { - In, - Out, - InOut - }; - - static const char *getDirectionAsString(PassDirection D); + static const char *getDirectionAsString(ParamCommandPassDirection D); - PassDirection getDirection() const LLVM_READONLY { - return static_cast<PassDirection>(ParamCommandCommentBits.Direction); + ParamCommandPassDirection getDirection() const LLVM_READONLY { + return static_cast<ParamCommandPassDirection>( + ParamCommandCommentBits.Direction); } bool isDirectionExplicit() const LLVM_READONLY { return ParamCommandCommentBits.IsDirectionExplicit; } - void setDirection(PassDirection Direction, bool Explicit) { - ParamCommandCommentBits.Direction = Direction; + void setDirection(ParamCommandPassDirection Direction, bool Explicit) { + ParamCommandCommentBits.Direction = llvm::to_underlying(Direction); ParamCommandCommentBits.IsDirectionExplicit = Explicit; } @@ -813,16 +807,13 @@ private: ArrayRef<unsigned> Position; public: - TParamCommandComment(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - CommandMarkerKind CommandMarker) : - BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID, - CommandMarker) - { } + TParamCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, + unsigned CommandID, CommandMarkerKind CommandMarker) + : BlockCommandComment(CommentKind::TParamCommandComment, LocBegin, LocEnd, + CommandID, CommandMarker) {} static bool classof(const Comment *C) { - return C->getCommentKind() == TParamCommandCommentKind; + return C->getCommentKind() == CommentKind::TParamCommandComment; } bool hasParamName() const { @@ -864,16 +855,13 @@ class VerbatimBlockLineComment : public Comment { StringRef Text; public: - VerbatimBlockLineComment(SourceLocation LocBegin, - StringRef Text) : - Comment(VerbatimBlockLineCommentKind, - LocBegin, - LocBegin.getLocWithOffset(Text.size())), - Text(Text) - { } + VerbatimBlockLineComment(SourceLocation LocBegin, StringRef Text) + : Comment(CommentKind::VerbatimBlockLineComment, LocBegin, + LocBegin.getLocWithOffset(Text.size())), + Text(Text) {} static bool classof(const Comment *C) { - return C->getCommentKind() == VerbatimBlockLineCommentKind; + return C->getCommentKind() == CommentKind::VerbatimBlockLineComment; } child_iterator child_begin() const { return nullptr; } @@ -895,16 +883,15 @@ protected: ArrayRef<VerbatimBlockLineComment *> Lines; public: - VerbatimBlockComment(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID) : - BlockCommandComment(VerbatimBlockCommentKind, - LocBegin, LocEnd, CommandID, - CMK_At) // FIXME: improve source fidelity. - { } + VerbatimBlockComment(SourceLocation LocBegin, SourceLocation LocEnd, + unsigned CommandID) + : BlockCommandComment(CommentKind::VerbatimBlockComment, LocBegin, LocEnd, + CommandID, + CMK_At) // FIXME: improve source fidelity. + {} static bool classof(const Comment *C) { - return C->getCommentKind() == VerbatimBlockCommentKind; + return C->getCommentKind() == CommentKind::VerbatimBlockComment; } child_iterator child_begin() const { @@ -946,21 +933,16 @@ protected: SourceLocation TextBegin; public: - VerbatimLineComment(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID, - SourceLocation TextBegin, - StringRef Text) : - BlockCommandComment(VerbatimLineCommentKind, - LocBegin, LocEnd, - CommandID, - CMK_At), // FIXME: improve source fidelity. - Text(Text), - TextBegin(TextBegin) - { } + VerbatimLineComment(SourceLocation LocBegin, SourceLocation LocEnd, + unsigned CommandID, SourceLocation TextBegin, + StringRef Text) + : BlockCommandComment(CommentKind::VerbatimLineComment, LocBegin, LocEnd, + CommandID, + CMK_At), // FIXME: improve source fidelity. + Text(Text), TextBegin(TextBegin) {} static bool classof(const Comment *C) { - return C->getCommentKind() == VerbatimLineCommentKind; + return C->getCommentKind() == CommentKind::VerbatimLineComment; } child_iterator child_begin() const { return nullptr; } @@ -1019,8 +1001,6 @@ struct DeclInfo { /// \li member function template, /// \li member function template specialization, /// \li ObjC method, - /// \li a typedef for a function pointer, member function pointer, - /// ObjC block. FunctionKind, /// Something that we consider a "class": @@ -1030,8 +1010,8 @@ struct DeclInfo { ClassKind, /// Something that we consider a "variable": - /// \li namespace scope variables; - /// \li static and non-static class data members; + /// \li namespace scope variables and variable templates; + /// \li static and non-static class data members and member templates; /// \li enumerators. VariableKind, @@ -1055,27 +1035,37 @@ struct DeclInfo { }; /// If false, only \c CommentDecl is valid. + LLVM_PREFERRED_TYPE(bool) unsigned IsFilled : 1; /// Simplified kind of \c CommentDecl, see \c DeclKind enum. + LLVM_PREFERRED_TYPE(DeclKind) unsigned Kind : 3; /// Is \c CommentDecl a template declaration. + LLVM_PREFERRED_TYPE(TemplateDeclKind) unsigned TemplateKind : 2; /// Is \c CommentDecl an ObjCMethodDecl. + LLVM_PREFERRED_TYPE(bool) unsigned IsObjCMethod : 1; /// Is \c CommentDecl a non-static member function of C++ class or /// instance method of ObjC class. /// Can be true only if \c IsFunctionDecl is true. + LLVM_PREFERRED_TYPE(bool) unsigned IsInstanceMethod : 1; /// Is \c CommentDecl a static member function of C++ class or /// class method of ObjC class. /// Can be true only if \c IsFunctionDecl is true. + LLVM_PREFERRED_TYPE(bool) unsigned IsClassMethod : 1; + /// Is \c CommentDecl something we consider a "function" that's variadic. + LLVM_PREFERRED_TYPE(bool) + unsigned IsVariadic : 1; + void fill(); DeclKind getKind() const LLVM_READONLY { @@ -1085,6 +1075,8 @@ struct DeclInfo { TemplateDeclKind getTemplateKind() const LLVM_READONLY { return static_cast<TemplateDeclKind>(TemplateKind); } + + bool involvesFunctionType() const { return !ReturnType.isNull(); } }; /// A full comment attached to a declaration, contains block content. @@ -1093,9 +1085,9 @@ class FullComment : public Comment { DeclInfo *ThisDeclInfo; public: - FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) : - Comment(FullCommentKind, SourceLocation(), SourceLocation()), - Blocks(Blocks), ThisDeclInfo(D) { + FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) + : Comment(CommentKind::FullComment, SourceLocation(), SourceLocation()), + Blocks(Blocks), ThisDeclInfo(D) { if (Blocks.empty()) return; @@ -1105,7 +1097,7 @@ public: } static bool classof(const Comment *C) { - return C->getCommentKind() == FullCommentKind; + return C->getCommentKind() == CommentKind::FullComment; } child_iterator child_begin() const { diff --git a/contrib/llvm-project/clang/include/clang/AST/CommentCommands.td b/contrib/llvm-project/clang/include/clang/AST/CommentCommands.td index fbbfc9f7e0b7..e839031752cd 100644 --- a/contrib/llvm-project/clang/include/clang/AST/CommentCommands.td +++ b/contrib/llvm-project/clang/include/clang/AST/CommentCommands.td @@ -31,6 +31,7 @@ class Command<string name> { } class InlineCommand<string name> : Command<name> { + let NumArgs = 1; let IsInlineCommand = 1; } @@ -62,6 +63,11 @@ class VerbatimLineCommand<string name> : Command<name> { let IsVerbatimLineCommand = 1; } +class PropertyCommand<string name> : Command<name> { + let NumArgs = 0; + let IsInlineCommand = 1; +} + class DeclarationVerbatimLineCommand<string name> : VerbatimLineCommand<name> { let IsDeclarationCommand = 1; @@ -86,9 +92,23 @@ def C : InlineCommand<"c">; def P : InlineCommand<"p">; def A : InlineCommand<"a">; def E : InlineCommand<"e">; +def N : InlineCommand<"n"> { let NumArgs = 0; } def Em : InlineCommand<"em">; -def Ref : InlineCommand<"ref">; -def Anchor : InlineCommand<"anchor">; +def Emoji : InlineCommand<"emoji">; + +def Anchor : InlineCommand<"anchor">; +def Ref : InlineCommand<"ref">; +def RefItem : InlineCommand<"refitem">; +def Cite : InlineCommand<"cite">; + +def CopyBrief : InlineCommand<"copybrief">; +def CopyDetails : InlineCommand<"copydetails">; +def CopyDoc : InlineCommand<"copydoc">; + +// Typically not used inline, but they take a single word. +def Extends : InlineCommand<"extends">; +def Implements : InlineCommand<"implements">; +def MemberOf : InlineCommand<"memberof">; //===----------------------------------------------------------------------===// // BlockCommand @@ -141,13 +161,15 @@ def Post : BlockCommand<"post">; def Pre : BlockCommand<"pre">; def Remark : BlockCommand<"remark">; def Remarks : BlockCommand<"remarks">; -def Retval : BlockCommand<"retval">; +def Retval : BlockCommand<"retval"> { let NumArgs = 1; } def Sa : BlockCommand<"sa">; def See : BlockCommand<"see">; def Since : BlockCommand<"since">; +def Test : BlockCommand<"test">; def Todo : BlockCommand<"todo">; def Version : BlockCommand<"version">; def Warning : BlockCommand<"warning">; +def XRefItem : BlockCommand<"xrefitem"> { let NumArgs = 3; } // HeaderDoc commands def Abstract : BlockCommand<"abstract"> { let IsBriefCommand = 1; } def ClassDesign : RecordLikeDetailCommand<"classdesign">; @@ -170,6 +192,8 @@ def SuperClass : RecordLikeDetailCommand<"superclass">; defm Code : VerbatimBlockCommand<"code", "endcode">; defm Verbatim : VerbatimBlockCommand<"verbatim", "endverbatim">; + +defm DocbookOnly : VerbatimBlockCommand<"docbookonly", "enddocbookonly">; defm Htmlonly : VerbatimBlockCommand<"htmlonly", "endhtmlonly">; defm Latexonly : VerbatimBlockCommand<"latexonly", "endlatexonly">; defm Xmlonly : VerbatimBlockCommand<"xmlonly", "endxmlonly">; @@ -178,10 +202,19 @@ defm Rtfonly : VerbatimBlockCommand<"rtfonly", "endrtfonly">; defm Dot : VerbatimBlockCommand<"dot", "enddot">; defm Msc : VerbatimBlockCommand<"msc", "endmsc">; +defm Uml : VerbatimBlockCommand<"startuml", "enduml">; + +// Actually not verbatim blocks, we should also parse commands within them. +defm Internal : VerbatimBlockCommand<"internal", "endinternal">; +// TODO: conflicts with HeaderDoc link, /link. +//defm Link : VerbatimBlockCommand<"link", "endlink">; +defm ParBlock : VerbatimBlockCommand<"parblock", "endparblock">; +defm SecRefList : VerbatimBlockCommand<"secreflist", "endsecreflist">; // These three commands have special support in CommentLexer to recognize their // names. def FDollar : VerbatimBlockCommand<"f$">; // Inline LaTeX formula +defm FParen : VerbatimBlockCommand<"f(", "f)">; // Inline LaTeX text defm FBracket : VerbatimBlockCommand<"f[", "f]">; // Displayed LaTeX formula defm FBrace : VerbatimBlockCommand<"f{", "f}">; // LaTeX environment @@ -199,11 +232,18 @@ def Addtogroup : VerbatimLineCommand<"addtogroup">; def Weakgroup : VerbatimLineCommand<"weakgroup">; def Name : VerbatimLineCommand<"name">; +// These actually take a single word, but it's optional. +// And they're used on a separate line typically, not inline. +def Dir : VerbatimLineCommand<"dir">; +def File : VerbatimLineCommand<"file">; + def Section : VerbatimLineCommand<"section">; def Subsection : VerbatimLineCommand<"subsection">; def Subsubsection : VerbatimLineCommand<"subsubsection">; def Paragraph : VerbatimLineCommand<"paragraph">; +def TableOfContents : VerbatimLineCommand<"tableofcontents">; +def Page : VerbatimLineCommand<"page">; def Mainpage : VerbatimLineCommand<"mainpage">; def Subpage : VerbatimLineCommand<"subpage">; @@ -212,13 +252,80 @@ def Related : VerbatimLineCommand<"related">; def RelatesAlso : VerbatimLineCommand<"relatesalso">; def RelatedAlso : VerbatimLineCommand<"relatedalso">; +def AddIndex : VerbatimLineCommand<"addindex">; + +// These take a single argument mostly, but since they include a file they'll +// typically be on their own line. +def DocbookInclude : VerbatimLineCommand<"docbookinclude">; +def DontInclude : VerbatimLineCommand<"dontinclude">; +def Example : VerbatimLineCommand<"example">; +def HtmlInclude : VerbatimLineCommand<"htmlinclude">; +def Include : VerbatimLineCommand<"include">; +def ManInclude : VerbatimLineCommand<"maninclude">; +def LatexInclude : VerbatimLineCommand<"latexinclude">; +def RtfInclude : VerbatimLineCommand<"rtfinclude">; +def Snippet : VerbatimLineCommand<"snippet">; +def VerbInclude : VerbatimLineCommand<"verbinclude">; +def XmlInclude : VerbatimLineCommand<"xmlinclude">; + +def Image : VerbatimLineCommand<"image">; +def DotFile : VerbatimLineCommand<"dotfile">; +def MscFile : VerbatimLineCommand<"mscfile">; +def DiaFile : VerbatimLineCommand<"diafile">; + +def Line : VerbatimLineCommand<"line">; +def Skip : VerbatimLineCommand<"skip">; +def SkipLine : VerbatimLineCommand<"skipline">; +def Until : VerbatimLineCommand<"until">; + +def NoOp : VerbatimLineCommand<"noop">; + +// We might also build proper support for if/ifnot/else/elseif/endif. +def If : VerbatimLineCommand<"if">; +def IfNot : VerbatimLineCommand<"ifnot">; +def Else : VerbatimLineCommand<"else">; +def ElseIf : VerbatimLineCommand<"elseif">; +def Endif : VerbatimLineCommand<"endif">; + +// Not treated as VerbatimBlockCommand because it spans multiple comments. +def Cond : VerbatimLineCommand<"cond">; +def EndCond : VerbatimLineCommand<"endcond">; + +//===----------------------------------------------------------------------===// +// PropertyCommand +//===----------------------------------------------------------------------===// + +def CallGraph : PropertyCommand<"callgraph">; +def HideCallGraph : PropertyCommand<"hidecallgraph">; +def CallerGraph : PropertyCommand<"callergraph">; +def HideCallerGraph : PropertyCommand<"hidecallergraph">; +def ShowInitializer : PropertyCommand<"showinitializer">; +def HideInitializer : PropertyCommand<"hideinitializer">; +def ShowRefBy : PropertyCommand<"showrefby">; +def HideRefBy : PropertyCommand<"hiderefby">; +def ShowRefs : PropertyCommand<"showrefs">; +def HideRefs : PropertyCommand<"hiderefs">; + +def Private : PropertyCommand<"private">; +def Protected : PropertyCommand<"protected">; +def Public : PropertyCommand<"public">; +def Pure : PropertyCommand<"pure">; +def Static : PropertyCommand<"static">; + +def NoSubgrouping : PropertyCommand<"nosubgrouping">; +def PrivateSection : PropertyCommand<"privatesection">; +def ProtectedSection : PropertyCommand<"protectedsection">; +def PublicSection : PropertyCommand<"publicsection">; + //===----------------------------------------------------------------------===// // DeclarationVerbatimLineCommand //===----------------------------------------------------------------------===// // Doxygen commands. +def Concept : DeclarationVerbatimLineCommand<"concept">; def Def : DeclarationVerbatimLineCommand<"def">; def Fn : DeclarationVerbatimLineCommand<"fn">; +def IDLExcept : DeclarationVerbatimLineCommand<"idlexcept">; def Namespace : DeclarationVerbatimLineCommand<"namespace">; def Overload : DeclarationVerbatimLineCommand<"overload">; def Property : DeclarationVerbatimLineCommand<"property">; diff --git a/contrib/llvm-project/clang/include/clang/AST/CommentHTMLTags.td b/contrib/llvm-project/clang/include/clang/AST/CommentHTMLTags.td index 251490094940..a1ce8c6da96c 100644 --- a/contrib/llvm-project/clang/include/clang/AST/CommentHTMLTags.td +++ b/contrib/llvm-project/clang/include/clang/AST/CommentHTMLTags.td @@ -52,11 +52,11 @@ def Tr : Tag<"tr"> { let EndTagOptional = 1; } def Th : Tag<"th"> { let EndTagOptional = 1; } def Td : Tag<"td"> { let EndTagOptional = 1; } -// Define a blacklist of attributes that are not safe to pass through to HTML +// Define a list of attributes that are not safe to pass through to HTML // output if the input is untrusted. // -// FIXME: this should be a whitelist. When changing this to a whitelist, don't -// forget to change the default in the TableGen backend. +// FIXME: This should be a list of attributes that _are_ safe. When changing +// this change, don't forget to change the default in the TableGen backend. class Attribute<string spelling> { string Spelling = spelling; bit IsSafeToPassThrough = 1; diff --git a/contrib/llvm-project/clang/include/clang/AST/CommentLexer.h b/contrib/llvm-project/clang/include/clang/AST/CommentLexer.h index 94f778501e75..9aa1681cb2c5 100644 --- a/contrib/llvm-project/clang/include/clang/AST/CommentLexer.h +++ b/contrib/llvm-project/clang/include/clang/AST/CommentLexer.h @@ -320,6 +320,9 @@ private: /// Eat string matching regexp \code \s*\* \endcode. void skipLineStartingDecorations(); + /// Skip over pure text. + const char *skipTextToken(); + /// Lex comment text, including commands if ParseCommands is set to true. void lexCommentText(Token &T); diff --git a/contrib/llvm-project/clang/include/clang/AST/CommentParser.h b/contrib/llvm-project/clang/include/clang/AST/CommentParser.h index 1a0cfb06e52b..e11e818b1af0 100644 --- a/contrib/llvm-project/clang/include/clang/AST/CommentParser.h +++ b/contrib/llvm-project/clang/include/clang/AST/CommentParser.h @@ -97,9 +97,8 @@ public: void parseTParamCommandArgs(TParamCommandComment *TPC, TextTokenRetokenizer &Retokenizer); - void parseBlockCommandArgs(BlockCommandComment *BC, - TextTokenRetokenizer &Retokenizer, - unsigned NumArgs); + ArrayRef<Comment::Argument> + parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs); BlockCommandComment *parseBlockCommand(); InlineCommandComment *parseInlineCommand(); diff --git a/contrib/llvm-project/clang/include/clang/AST/CommentSema.h b/contrib/llvm-project/clang/include/clang/AST/CommentSema.h index 6dfe0f4920d0..03f13283ac0d 100644 --- a/contrib/llvm-project/clang/include/clang/AST/CommentSema.h +++ b/contrib/llvm-project/clang/include/clang/AST/CommentSema.h @@ -80,7 +80,7 @@ public: ArrayRef<T> copyArray(ArrayRef<T> Source) { if (!Source.empty()) return Source.copy(Allocator); - return None; + return std::nullopt; } ParagraphComment *actOnParagraphComment( @@ -130,14 +130,8 @@ public: InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin, SourceLocation CommandLocEnd, - unsigned CommandID); - - InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin, - SourceLocation CommandLocEnd, unsigned CommandID, - SourceLocation ArgLocBegin, - SourceLocation ArgLocEnd, - StringRef Arg); + ArrayRef<Comment::Argument> Args); InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin, SourceLocation LocEnd, @@ -181,6 +175,7 @@ public: FullComment *actOnFullComment(ArrayRef<BlockContentComment *> Blocks); +private: void checkBlockCommandEmptyParagraph(BlockCommandComment *Command); void checkReturnsCommand(const BlockCommandComment *Command); @@ -198,19 +193,19 @@ public: void checkContainerDecl(const BlockCommandComment *Comment); /// Resolve parameter names to parameter indexes in function declaration. - /// Emit diagnostics about unknown parametrs. + /// Emit diagnostics about unknown parameters. void resolveParamCommandIndexes(const FullComment *FC); + /// \returns \c true if the declaration that this comment is attached to + /// is a pointer to function/method/block type or has such a type. + bool involvesFunctionType(); + bool isFunctionDecl(); bool isAnyFunctionDecl(); /// \returns \c true if declaration that this comment is attached to declares /// a function pointer. bool isFunctionPointerVarDecl(); - /// \returns \c true if the declaration that this comment is attached to - /// declares a variable or a field whose type is a function or a block - /// pointer. - bool isFunctionOrBlockPointerVarLikeDecl(); bool isFunctionOrMethodVariadic(); bool isObjCMethodDecl(); bool isObjCPropertyDecl(); @@ -249,8 +244,7 @@ public: StringRef Typo, const TemplateParameterList *TemplateParameters); - InlineCommandComment::RenderKind - getInlineCommandRenderKind(StringRef Name) const; + InlineCommandRenderKind getInlineCommandRenderKind(StringRef Name) const; }; } // end namespace comments diff --git a/contrib/llvm-project/clang/include/clang/AST/CommentVisitor.h b/contrib/llvm-project/clang/include/clang/AST/CommentVisitor.h index d9a7439f7cc0..bbb624a23e68 100644 --- a/contrib/llvm-project/clang/include/clang/AST/CommentVisitor.h +++ b/contrib/llvm-project/clang/include/clang/AST/CommentVisitor.h @@ -31,8 +31,9 @@ public: switch (C->getCommentKind()) { default: llvm_unreachable("Unknown comment kind!"); #define ABSTRACT_COMMENT(COMMENT) -#define COMMENT(CLASS, PARENT) \ - case Comment::CLASS##Kind: DISPATCH(CLASS, CLASS); +#define COMMENT(CLASS, PARENT) \ + case CommentKind::CLASS: \ + DISPATCH(CLASS, CLASS); #include "clang/AST/CommentNodes.inc" #undef ABSTRACT_COMMENT #undef COMMENT diff --git a/contrib/llvm-project/clang/include/clang/AST/ComparisonCategories.h b/contrib/llvm-project/clang/include/clang/AST/ComparisonCategories.h index b41e934142ee..b4ad37e394ce 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ComparisonCategories.h +++ b/contrib/llvm-project/clang/include/clang/AST/ComparisonCategories.h @@ -19,6 +19,7 @@ #include "llvm/ADT/DenseMap.h" #include <array> #include <cassert> +#include <optional> #include <vector> namespace llvm { @@ -38,9 +39,8 @@ class NamespaceDecl; /// An enumeration representing the different comparison categories /// types. /// -/// C++2a [cmp.categories.pre] The types weak_equality, strong_equality, -/// partial_ordering, weak_ordering, and strong_ordering are collectively -/// termed the comparison category types. +/// C++20 [cmp.categories.pre] The types partial_ordering, weak_ordering, and +/// strong_ordering are collectively termed the comparison category types. enum class ComparisonCategoryType : unsigned char { PartialOrdering, WeakOrdering, @@ -58,7 +58,8 @@ inline ComparisonCategoryType commonComparisonType(ComparisonCategoryType A, /// Get the comparison category that should be used when comparing values of /// type \c T. -Optional<ComparisonCategoryType> getComparisonCategoryForBuiltinCmp(QualType T); +std::optional<ComparisonCategoryType> +getComparisonCategoryForBuiltinCmp(QualType T); /// An enumeration representing the possible results of a three-way /// comparison. These values map onto instances of comparison category types @@ -115,8 +116,7 @@ private: public: /// The declaration for the comparison category type from the /// standard library. - // FIXME: Make this const - CXXRecordDecl *Record = nullptr; + const CXXRecordDecl *Record = nullptr; /// The Kind of the comparison category type ComparisonCategoryType Kind; @@ -146,7 +146,7 @@ public: return Kind == CCK::PartialOrdering; } - /// Converts the specified result kind into the the correct result kind + /// Converts the specified result kind into the correct result kind /// for this category. Specifically it lowers strong equality results to /// weak equivalence if needed. ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const { diff --git a/contrib/llvm-project/clang/include/clang/AST/ComputeDependence.h b/contrib/llvm-project/clang/include/clang/AST/ComputeDependence.h index 8db09e6b57d0..f62611cb4c3c 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ComputeDependence.h +++ b/contrib/llvm-project/clang/include/clang/AST/ComputeDependence.h @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_COMPUTE_DEPENDENCE_H -#define LLVM_CLANG_AST_COMPUTE_DEPENDENCE_H +#ifndef LLVM_CLANG_AST_COMPUTEDEPENDENCE_H +#define LLVM_CLANG_AST_COMPUTEDEPENDENCE_H #include "clang/AST/DependenceFlags.h" #include "clang/Basic/ExceptionSpecificationType.h" @@ -30,7 +30,8 @@ class UnaryExprOrTypeTraitExpr; class ArraySubscriptExpr; class MatrixSubscriptExpr; class CompoundLiteralExpr; -class CastExpr; +class ImplicitCastExpr; +class ExplicitCastExpr; class BinaryOperator; class ConditionalOperator; class BinaryConditionalOperator; @@ -70,6 +71,7 @@ class CXXPseudoDestructorExpr; class OverloadExpr; class DependentScopeDeclRefExpr; class CXXConstructExpr; +class CXXTemporaryObjectExpr; class CXXDefaultInitExpr; class CXXDefaultArgExpr; class LambdaExpr; @@ -77,6 +79,7 @@ class CXXUnresolvedConstructExpr; class CXXDependentScopeMemberExpr; class MaterializeTemporaryExpr; class CXXFoldExpr; +class CXXParenListInitExpr; class TypeTraitExpr; class ConceptSpecializationExpr; class SYCLUniqueStableNameExpr; @@ -114,7 +117,8 @@ ExprDependence computeDependence(UnaryExprOrTypeTraitExpr *E); ExprDependence computeDependence(ArraySubscriptExpr *E); ExprDependence computeDependence(MatrixSubscriptExpr *E); ExprDependence computeDependence(CompoundLiteralExpr *E); -ExprDependence computeDependence(CastExpr *E); +ExprDependence computeDependence(ImplicitCastExpr *E); +ExprDependence computeDependence(ExplicitCastExpr *E); ExprDependence computeDependence(BinaryOperator *E); ExprDependence computeDependence(ConditionalOperator *E); ExprDependence computeDependence(BinaryConditionalOperator *E); @@ -156,6 +160,7 @@ ExprDependence computeDependence(OverloadExpr *E, bool KnownDependent, bool KnownContainsUnexpandedParameterPack); ExprDependence computeDependence(DependentScopeDeclRefExpr *E); ExprDependence computeDependence(CXXConstructExpr *E); +ExprDependence computeDependence(CXXTemporaryObjectExpr *E); ExprDependence computeDependence(CXXDefaultInitExpr *E); ExprDependence computeDependence(CXXDefaultArgExpr *E); ExprDependence computeDependence(LambdaExpr *E, @@ -164,6 +169,7 @@ ExprDependence computeDependence(CXXUnresolvedConstructExpr *E); ExprDependence computeDependence(CXXDependentScopeMemberExpr *E); ExprDependence computeDependence(MaterializeTemporaryExpr *E); ExprDependence computeDependence(CXXFoldExpr *E); +ExprDependence computeDependence(CXXParenListInitExpr *E); ExprDependence computeDependence(TypeTraitExpr *E); ExprDependence computeDependence(ConceptSpecializationExpr *E, bool ValueDependent); diff --git a/contrib/llvm-project/clang/include/clang/AST/CurrentSourceLocExprScope.h b/contrib/llvm-project/clang/include/clang/AST/CurrentSourceLocExprScope.h index 4ebbdf63abb5..4f8343efad16 100644 --- a/contrib/llvm-project/clang/include/clang/AST/CurrentSourceLocExprScope.h +++ b/contrib/llvm-project/clang/include/clang/AST/CurrentSourceLocExprScope.h @@ -1,9 +1,8 @@ //===--- CurrentSourceLocExprScope.h ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -12,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_CURRENT_SOURCE_LOC_EXPR_SCOPE_H -#define LLVM_CLANG_AST_CURRENT_SOURCE_LOC_EXPR_SCOPE_H +#ifndef LLVM_CLANG_AST_CURRENTSOURCELOCEXPRSCOPE_H +#define LLVM_CLANG_AST_CURRENTSOURCELOCEXPRSCOPE_H #include <cassert> @@ -72,4 +71,4 @@ private: } // end namespace clang -#endif // LLVM_CLANG_AST_CURRENT_SOURCE_LOC_EXPR_SCOPE_H +#endif // LLVM_CLANG_AST_CURRENTSOURCELOCEXPRSCOPE_H diff --git a/contrib/llvm-project/clang/include/clang/AST/Decl.h b/contrib/llvm-project/clang/include/clang/AST/Decl.h index 30a9458bc2ee..f26fb5ad5f13 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Decl.h +++ b/contrib/llvm-project/clang/include/clang/AST/Decl.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_AST_DECL_H #define LLVM_CLANG_AST_DECL_H +#include "clang/AST/APNumericStorage.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTContextAllocate.h" #include "clang/AST/DeclAccessPair.h" @@ -35,7 +36,6 @@ #include "clang/Basic/Visibility.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h" @@ -46,6 +46,7 @@ #include <cassert> #include <cstddef> #include <cstdint> +#include <optional> #include <string> #include <utility> @@ -53,7 +54,6 @@ namespace clang { class ASTContext; struct ASTTemplateArgumentListInfo; -class Attr; class CompoundStmt; class DependentFunctionTemplateSpecializationInfo; class EnumDecl; @@ -74,9 +74,9 @@ class TemplateArgumentList; class TemplateArgumentListInfo; class TemplateParameterList; class TypeAliasTemplateDecl; -class TypeLoc; class UnresolvedSetImpl; class VarTemplateDecl; +enum class ImplicitParamKind; /// The top declaration context. class TranslationUnitDecl : public Decl, @@ -293,7 +293,9 @@ public: /// Pretty-print the unqualified name of this declaration. Can be overloaded /// by derived classes to provide a more user-friendly name when appropriate. - virtual void printName(raw_ostream &os) const; + virtual void printName(raw_ostream &OS, const PrintingPolicy &Policy) const; + /// Calls printName() with the ASTContext printing policy from the decl. + void printName(raw_ostream &OS) const; /// Get the actual, stored name of the declaration, which may be a special /// name. @@ -357,7 +359,8 @@ public: /// /// \param IsKnownNewer \c true if this declaration is known to be newer /// than \p OldD (for instance, if this declaration is newly-created). - bool declarationReplaces(NamedDecl *OldD, bool IsKnownNewer = true) const; + bool declarationReplaces(const NamedDecl *OldD, + bool IsKnownNewer = true) const; /// Determine whether this declaration has linkage. bool hasLinkage() const; @@ -395,9 +398,7 @@ public: /// Get the linkage from a semantic point of view. Entities in /// anonymous namespaces are external (in c++98). - Linkage getFormalLinkage() const { - return clang::getFormalLinkage(getLinkageInternal()); - } + Linkage getFormalLinkage() const; /// True if this decl has external linkage. bool hasExternalFormalLinkage() const { @@ -437,7 +438,7 @@ public: /// If visibility was explicitly specified for this /// declaration, return that visibility. - Optional<Visibility> + std::optional<Visibility> getExplicitVisibility(ExplicitVisibilityKind kind) const; /// True if the computed linkage is valid. Used for consistency @@ -454,6 +455,8 @@ public: return hasCachedLinkage(); } + bool isPlaceholderVar(const LangOptions &LangOpts) const; + /// Looks through UsingDecls and ObjCCompatibleAliasDecls for /// the underlying named decl. NamedDecl *getUnderlyingDecl() { @@ -542,6 +545,9 @@ public: class NamespaceDecl : public NamedDecl, public DeclContext, public Redeclarable<NamespaceDecl> { + + enum Flags : unsigned { F_Inline = 1 << 0, F_Nested = 1 << 1 }; + /// The starting location of the source range, pointing /// to either the namespace or the inline keyword. SourceLocation LocStart; @@ -553,11 +559,12 @@ class NamespaceDecl : public NamedDecl, public DeclContext, /// this namespace or to the first namespace in the chain (the latter case /// only when this is not the first in the chain), along with a /// boolean value indicating whether this is an inline namespace. - llvm::PointerIntPair<NamespaceDecl *, 1, bool> AnonOrFirstNamespaceAndInline; + llvm::PointerIntPair<NamespaceDecl *, 2, unsigned> + AnonOrFirstNamespaceAndFlags; NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline, SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, NamespaceDecl *PrevDecl); + IdentifierInfo *Id, NamespaceDecl *PrevDecl, bool Nested); using redeclarable_base = Redeclarable<NamespaceDecl>; @@ -569,10 +576,10 @@ public: friend class ASTDeclReader; friend class ASTDeclWriter; - static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, - bool Inline, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - NamespaceDecl *PrevDecl); + static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, bool Inline, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, NamespaceDecl *PrevDecl, + bool Nested); static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -601,12 +608,33 @@ public: /// Returns true if this is an inline namespace declaration. bool isInline() const { - return AnonOrFirstNamespaceAndInline.getInt(); + return AnonOrFirstNamespaceAndFlags.getInt() & F_Inline; } /// Set whether this is an inline namespace declaration. void setInline(bool Inline) { - AnonOrFirstNamespaceAndInline.setInt(Inline); + unsigned F = AnonOrFirstNamespaceAndFlags.getInt(); + if (Inline) + AnonOrFirstNamespaceAndFlags.setInt(F | F_Inline); + else + AnonOrFirstNamespaceAndFlags.setInt(F & ~F_Inline); + } + + /// Returns true if this is a nested namespace declaration. + /// \code + /// namespace outer::nested { } + /// \endcode + bool isNested() const { + return AnonOrFirstNamespaceAndFlags.getInt() & F_Nested; + } + + /// Set whether this is a nested namespace declaration. + void setNested(bool Nested) { + unsigned F = AnonOrFirstNamespaceAndFlags.getInt(); + if (Nested) + AnonOrFirstNamespaceAndFlags.setInt(F | F_Nested); + else + AnonOrFirstNamespaceAndFlags.setInt(F & ~F_Nested); } /// Returns true if the inline qualifier for \c Name is redundant. @@ -614,7 +642,9 @@ public: if (!isInline()) return false; auto X = lookup(Name); - auto Y = getParent()->lookup(Name); + // We should not perform a lookup within a transparent context, so find a + // non-transparent parent context. + auto Y = getParent()->getNonTransparentContext()->lookup(Name); return std::distance(X.begin(), X.end()) == std::distance(Y.begin(), Y.end()); } @@ -633,11 +663,11 @@ public: /// Retrieve the anonymous namespace nested inside this namespace, /// if any. NamespaceDecl *getAnonymousNamespace() const { - return getOriginalNamespace()->AnonOrFirstNamespaceAndInline.getPointer(); + return getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.getPointer(); } void setAnonymousNamespace(NamespaceDecl *D) { - getOriginalNamespace()->AnonOrFirstNamespaceAndInline.setPointer(D); + getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.setPointer(D); } /// Retrieves the canonical declaration of this namespace. @@ -668,6 +698,8 @@ public: } }; +class VarDecl; + /// Represent the declaration of a variable (in which case it is /// an lvalue) a function (in which case it is a function designator) or /// an enum constant. @@ -689,6 +721,18 @@ public: /// or declared with the weak or weak-ref attr. bool isWeak() const; + /// Whether this variable is the implicit variable for a lambda init-capture. + /// Only VarDecl can be init captures, but both VarDecl and BindingDecl + /// can be captured. + bool isInitCapture() const; + + // If this is a VarDecl, or a BindindDecl with an + // associated decomposed VarDecl, return that VarDecl. + VarDecl *getPotentiallyDecomposedVarDecl(); + const VarDecl *getPotentiallyDecomposedVarDecl() const { + return const_cast<ValueDecl *>(this)->getPotentiallyDecomposedVarDecl(); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; } @@ -861,7 +905,7 @@ struct EvaluatedStmt { bool HasICEInit : 1; bool CheckedForICEInit : 1; - Stmt *Value; + LazyDeclStmtPtr Value; APValue Evaluated; EvaluatedStmt() @@ -882,7 +926,10 @@ public: CallInit, /// Direct list-initialization (C++11) - ListInit + ListInit, + + /// Parenthesized list-initialization (C++20) + ParenListInit }; /// Kinds of thread-local storage. @@ -925,12 +972,16 @@ private: friend class ASTDeclReader; friend class VarDecl; + LLVM_PREFERRED_TYPE(StorageClass) unsigned SClass : 3; + LLVM_PREFERRED_TYPE(ThreadStorageClassSpecifier) unsigned TSCSpec : 2; + LLVM_PREFERRED_TYPE(InitializationStyle) unsigned InitStyle : 2; /// Whether this variable is an ARC pseudo-__strong variable; see /// isARCPseudoStrong() for details. + LLVM_PREFERRED_TYPE(bool) unsigned ARCPseudoStrong : 1; }; enum { NumVarDeclBits = 8 }; @@ -951,22 +1002,27 @@ protected: friend class ASTDeclReader; friend class ParmVarDecl; + LLVM_PREFERRED_TYPE(VarDeclBitfields) unsigned : NumVarDeclBits; /// Whether this parameter inherits a default argument from a /// prior declaration. + LLVM_PREFERRED_TYPE(bool) unsigned HasInheritedDefaultArg : 1; /// Describes the kind of default argument for this parameter. By default /// this is none. If this is normal, then the default argument is stored in /// the \c VarDecl initializer expression unless we were unable to parse /// (even an invalid) expression for the default argument. + LLVM_PREFERRED_TYPE(DefaultArgKind) unsigned DefaultArgKind : 2; /// Whether this parameter undergoes K&R argument promotion. + LLVM_PREFERRED_TYPE(bool) unsigned IsKNRPromoted : 1; /// Whether this parameter is an ObjC method parameter or not. + LLVM_PREFERRED_TYPE(bool) unsigned IsObjCMethodParam : 1; /// If IsObjCMethodParam, a Decl::ObjCDeclQualifier. @@ -985,51 +1041,64 @@ protected: friend class ImplicitParamDecl; friend class VarDecl; + LLVM_PREFERRED_TYPE(VarDeclBitfields) unsigned : NumVarDeclBits; // FIXME: We need something similar to CXXRecordDecl::DefinitionData. /// Whether this variable is a definition which was demoted due to /// module merge. + LLVM_PREFERRED_TYPE(bool) unsigned IsThisDeclarationADemotedDefinition : 1; /// Whether this variable is the exception variable in a C++ catch /// or an Objective-C @catch statement. + LLVM_PREFERRED_TYPE(bool) unsigned ExceptionVar : 1; /// Whether this local variable could be allocated in the return /// slot of its function, enabling the named return value optimization /// (NRVO). + LLVM_PREFERRED_TYPE(bool) unsigned NRVOVariable : 1; /// Whether this variable is the for-range-declaration in a C++0x /// for-range statement. + LLVM_PREFERRED_TYPE(bool) unsigned CXXForRangeDecl : 1; /// Whether this variable is the for-in loop declaration in Objective-C. + LLVM_PREFERRED_TYPE(bool) unsigned ObjCForDecl : 1; /// Whether this variable is (C++1z) inline. + LLVM_PREFERRED_TYPE(bool) unsigned IsInline : 1; /// Whether this variable has (C++1z) inline explicitly specified. + LLVM_PREFERRED_TYPE(bool) unsigned IsInlineSpecified : 1; /// Whether this variable is (C++0x) constexpr. + LLVM_PREFERRED_TYPE(bool) unsigned IsConstexpr : 1; /// Whether this variable is the implicit variable for a lambda /// init-capture. + LLVM_PREFERRED_TYPE(bool) unsigned IsInitCapture : 1; /// Whether this local extern variable's previous declaration was /// declared in the same block scope. This controls whether we should merge /// the type of this declaration with its previous declaration. + LLVM_PREFERRED_TYPE(bool) unsigned PreviousDeclInSameBlockScope : 1; /// Defines kind of the ImplicitParamDecl: 'this', 'self', 'vtt', '_cmd' or /// something else. + LLVM_PREFERRED_TYPE(ImplicitParamKind) unsigned ImplicitParamKind : 3; + LLVM_PREFERRED_TYPE(bool) unsigned EscapingByref : 1; }; @@ -1041,7 +1110,7 @@ protected: }; VarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, QualType T, + SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass SC); using redeclarable_base = Redeclarable<VarDecl>; @@ -1071,8 +1140,8 @@ public: static VarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S); + const IdentifierInfo *Id, QualType T, + TypeSourceInfo *TInfo, StorageClass S); static VarDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1316,12 +1385,15 @@ public: EvaluatedStmt *getEvaluatedStmt() const; /// Attempt to evaluate the value of the initializer attached to this - /// declaration, and produce notes explaining why it cannot be evaluated or is - /// not a constant expression. Returns a pointer to the value if evaluation - /// succeeded, 0 otherwise. + /// declaration, and produce notes explaining why it cannot be evaluated. + /// Returns a pointer to the value if evaluation succeeded, 0 otherwise. APValue *evaluateValue() const; - APValue *evaluateValue(SmallVectorImpl<PartialDiagnosticAt> &Notes) const; +private: + APValue *evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &Notes, + bool IsConstantInitialization) const; + +public: /// Return the already-evaluated value of this variable's /// initializer, or NULL if the value is not yet known. Returns pointer /// to untyped APValue if the value could not be evaluated. @@ -1588,38 +1660,55 @@ public: /// kind? QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const; + /// Whether this variable has a flexible array member initialized with one + /// or more elements. This can only be called for declarations where + /// hasInit() is true. + /// + /// (The standard doesn't allow initializing flexible array members; this is + /// a gcc/msvc extension.) + bool hasFlexibleArrayInit(const ASTContext &Ctx) const; + + /// If hasFlexibleArrayInit is true, compute the number of additional bytes + /// necessary to store those elements. Otherwise, returns zero. + /// + /// This can only be called for declarations where hasInit() is true. + CharUnits getFlexibleArrayInitChars(const ASTContext &Ctx) const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; } }; -class ImplicitParamDecl : public VarDecl { - void anchor() override; +/// Defines the kind of the implicit parameter: is this an implicit parameter +/// with pointer to 'this', 'self', '_cmd', virtual table pointers, captured +/// context or something else. +enum class ImplicitParamKind { + /// Parameter for Objective-C 'self' argument + ObjCSelf, -public: - /// Defines the kind of the implicit parameter: is this an implicit parameter - /// with pointer to 'this', 'self', '_cmd', virtual table pointers, captured - /// context or something else. - enum ImplicitParamKind : unsigned { - /// Parameter for Objective-C 'self' argument - ObjCSelf, + /// Parameter for Objective-C '_cmd' argument + ObjCCmd, - /// Parameter for Objective-C '_cmd' argument - ObjCCmd, + /// Parameter for C++ 'this' argument + CXXThis, - /// Parameter for C++ 'this' argument - CXXThis, + /// Parameter for C++ virtual table pointers + CXXVTT, - /// Parameter for C++ virtual table pointers - CXXVTT, + /// Parameter for captured context + CapturedContext, - /// Parameter for captured context - CapturedContext, + /// Parameter for Thread private variable + ThreadPrivateVar, - /// Other implicit parameter - Other, - }; + /// Other implicit parameter + Other, +}; +class ImplicitParamDecl : public VarDecl { + void anchor() override; + +public: /// Create implicit parameter. static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, @@ -1634,7 +1723,7 @@ public: ImplicitParamKind ParamKind) : VarDecl(ImplicitParam, C, DC, IdLoc, IdLoc, Id, Type, /*TInfo=*/nullptr, SC_None) { - NonParmVarDeclBits.ImplicitParamKind = ParamKind; + NonParmVarDeclBits.ImplicitParamKind = llvm::to_underlying(ParamKind); setImplicit(); } @@ -1642,7 +1731,7 @@ public: : VarDecl(ImplicitParam, C, /*DC=*/nullptr, SourceLocation(), SourceLocation(), /*Id=*/nullptr, Type, /*TInfo=*/nullptr, SC_None) { - NonParmVarDeclBits.ImplicitParamKind = ParamKind; + NonParmVarDeclBits.ImplicitParamKind = llvm::to_underlying(ParamKind); setImplicit(); } @@ -1745,6 +1834,18 @@ public: ParmVarDeclBits.IsKNRPromoted = promoted; } + bool isExplicitObjectParameter() const { + return ExplicitObjectParameterIntroducerLoc.isValid(); + } + + void setExplicitObjectParameterLoc(SourceLocation Loc) { + ExplicitObjectParameterIntroducerLoc = Loc; + } + + SourceLocation getExplicitObjectParamThisLoc() const { + return ExplicitObjectParameterIntroducerLoc; + } + Expr *getDefaultArg(); const Expr *getDefaultArg() const { return const_cast<ParmVarDecl *>(this)->getDefaultArg(); @@ -1811,7 +1912,10 @@ public: static bool classofKind(Kind K) { return K == ParmVar; } private: + friend class ASTDeclReader; + enum { ParameterIndexSentinel = (1 << NumParameterIndexBits) - 1 }; + SourceLocation ExplicitObjectParameterIntroducerLoc; void setParameterIndex(unsigned parameterIndex) { if (parameterIndex >= ParameterIndexSentinel) { @@ -1835,7 +1939,9 @@ enum class MultiVersionKind { None, Target, CPUSpecific, - CPUDispatch + CPUDispatch, + TargetClones, + TargetVersion }; /// Represents a function declaration or definition. @@ -1869,7 +1975,10 @@ public: TK_FunctionTemplateSpecialization, // A function template specialization that hasn't yet been resolved to a // particular specialized function template. - TK_DependentFunctionTemplateSpecialization + TK_DependentFunctionTemplateSpecialization, + // A non-template function which is in a dependent scope. + TK_DependentNonTemplate + }; /// Stashed information about a defaulted function definition whose body has @@ -1915,23 +2024,26 @@ private: /// EndRangeLoc. SourceLocation EndRangeLoc; + SourceLocation DefaultKWLoc; + /// The template or declaration that this declaration /// describes or was instantiated from, respectively. /// - /// For non-templates, this value will be NULL. For function - /// declarations that describe a function template, this will be a - /// pointer to a FunctionTemplateDecl. For member functions - /// of class template specializations, this will be a MemberSpecializationInfo + /// For non-templates this value will be NULL, unless this declaration was + /// declared directly inside of a function template, in which case it will + /// have a pointer to a FunctionDecl, stored in the NamedDecl. For function + /// declarations that describe a function template, this will be a pointer to + /// a FunctionTemplateDecl, stored in the NamedDecl. For member functions of + /// class template specializations, this will be a MemberSpecializationInfo /// pointer containing information about the specialization. /// For function template specializations, this will be a /// FunctionTemplateSpecializationInfo, which contains information about /// the template being specialized and the template arguments involved in /// that specialization. - llvm::PointerUnion<FunctionTemplateDecl *, - MemberSpecializationInfo *, + llvm::PointerUnion<NamedDecl *, MemberSpecializationInfo *, FunctionTemplateSpecializationInfo *, DependentFunctionTemplateSpecializationInfo *> - TemplateOrSpecialization; + TemplateOrSpecialization; /// Provides source/type location info for the declaration name embedded in /// the DeclaratorDecl base class. @@ -1987,8 +2099,8 @@ private: protected: FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, StorageClass S, bool isInlineSpecified, - ConstexprSpecKind ConstexprKind, + TypeSourceInfo *TInfo, StorageClass S, bool UsesFPIntrin, + bool isInlineSpecified, ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause = nullptr); using redeclarable_base = Redeclarable<FunctionDecl>; @@ -2022,23 +2134,23 @@ public: static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, - TypeSourceInfo *TInfo, StorageClass SC, bool isInlineSpecified = false, - bool hasWrittenPrototype = true, + TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin = false, + bool isInlineSpecified = false, bool hasWrittenPrototype = true, ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified, Expr *TrailingRequiresClause = nullptr) { DeclarationNameInfo NameInfo(N, NLoc); return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, SC, - isInlineSpecified, hasWrittenPrototype, - ConstexprKind, TrailingRequiresClause); + UsesFPIntrin, isInlineSpecified, + hasWrittenPrototype, ConstexprKind, + TrailingRequiresClause); } - static FunctionDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, StorageClass SC, - bool isInlineSpecified, bool hasWrittenPrototype, - ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause); + static FunctionDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + StorageClass SC, bool UsesFPIntrin, bool isInlineSpecified, + bool hasWrittenPrototype, ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause); static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2098,7 +2210,7 @@ public: /// declaration to the declaration that is a definition (if there is one). /// /// \param CheckForPendingFriendDefinition If \c true, also check for friend - /// declarations that were instantiataed from function definitions. + /// declarations that were instantiated from function definitions. /// Such a declaration behaves as if it is a definition for the /// purpose of redefinition checking, but isn't actually a "real" /// definition until its body is instantiated. @@ -2182,8 +2294,8 @@ public: /// Whether this virtual function is pure, i.e. makes the containing class /// abstract. - bool isPure() const { return FunctionDeclBits.IsPure; } - void setPure(bool P = true); + bool isPureVirtual() const { return FunctionDeclBits.IsPureVirtual; } + void setIsPureVirtual(bool P = true); /// Whether this templated function will be late parsed. bool isLateTemplateParsed() const { @@ -2220,6 +2332,16 @@ public: FunctionDeclBits.IsExplicitlyDefaulted = ED; } + SourceLocation getDefaultLoc() const { + return isExplicitlyDefaulted() ? DefaultKWLoc : SourceLocation(); + } + + void setDefaultLoc(SourceLocation NewLoc) { + assert((NewLoc.isInvalid() || isExplicitlyDefaulted()) && + "Can't set default loc is function isn't explicitly defaulted"); + DefaultKWLoc = NewLoc; + } + /// True if this method is user-declared and was not /// deleted or defaulted on its first declaration. bool isUserProvided() const { @@ -2230,6 +2352,13 @@ public: DeclAsWritten->getCanonicalDecl()->isDefaulted()); } + bool isIneligibleOrNotSelected() const { + return FunctionDeclBits.IsIneligibleOrNotSelected; + } + void setIneligibleOrNotSelected(bool II) { + FunctionDeclBits.IsIneligibleOrNotSelected = II; + } + /// Whether falling off this function implicitly returns null/zero. /// If a more specific implicit return value is required, front-ends /// should synthesize the appropriate return statements. @@ -2291,6 +2420,21 @@ public: return getConstexprKind() == ConstexprSpecKind::Consteval; } + void setBodyContainsImmediateEscalatingExpressions(bool Set) { + FunctionDeclBits.BodyContainsImmediateEscalatingExpression = Set; + } + + bool BodyContainsImmediateEscalatingExpressions() const { + return FunctionDeclBits.BodyContainsImmediateEscalatingExpression; + } + + bool isImmediateEscalating() const; + + // The function is a C++ immediate function. + // This can be either a consteval function, or an immediate escalating + // function containing an immediate escalating expression. + bool isImmediateFunction() const; + /// Whether the instantiation of this function is pending. /// This bit is set when the decision to instantiate this function is made /// and unset if and when the function body is created. That leaves out @@ -2385,7 +2529,7 @@ public: /// If this function is an allocation/deallocation function that takes /// the `std::nothrow_t` tag, return true through IsNothrow, bool isReplaceableGlobalAllocationFunction( - Optional<unsigned> *AlignmentParam = nullptr, + std::optional<unsigned> *AlignmentParam = nullptr, bool *IsNothrow = nullptr) const; /// Determine if this function provides an inline implementation of a builtin. @@ -2437,6 +2581,23 @@ public: getCanonicalDecl()->FunctionDeclBits.IsMultiVersion = V; } + // Sets that this is a constrained friend where the constraint refers to an + // enclosing template. + void setFriendConstraintRefersToEnclosingTemplate(bool V = true) { + getCanonicalDecl() + ->FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate = V; + } + // Indicates this function is a constrained friend, where the constraint + // refers to an enclosing template for hte purposes of [temp.friend]p9. + bool FriendConstraintRefersToEnclosingTemplate() const { + return getCanonicalDecl() + ->FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate; + } + + /// Determine whether a function is a friend function that cannot be + /// redeclared outside of its class, per C++ [temp.friend]p9. + bool isMemberLikeConstrainedFriend() const; + /// Gets the kind of multiversioning attribute this declaration has. Note that /// this can return a value even if the function is not multiversion, such as /// the case of 'target'. @@ -2454,6 +2615,10 @@ public: /// the target functionality. bool isTargetMultiVersion() const; + /// True if this function is a multiversioned dispatch function as a part of + /// the target-clones functionality. + bool isTargetClonesMultiVersion() const; + /// \brief Get the associated-constraints of this function declaration. /// Currently, this will either be a vector of size 1 containing the /// trailing-requires-clause or an empty vector. @@ -2515,6 +2680,23 @@ public: /// parameters have default arguments (in C++). unsigned getMinRequiredArguments() const; + /// Returns the minimum number of non-object arguments needed to call this + /// function. This produces the same value as getMinRequiredArguments except + /// it does not count the explicit object argument, if any. + unsigned getMinRequiredExplicitArguments() const; + + bool hasCXXExplicitFunctionObjectParameter() const; + + unsigned getNumNonObjectParams() const; + + const ParmVarDecl *getNonObjectParameter(unsigned I) const { + return getParamDecl(hasCXXExplicitFunctionObjectParameter() ? I + 1 : I); + } + + ParmVarDecl *getNonObjectParameter(unsigned I) { + return getParamDecl(hasCXXExplicitFunctionObjectParameter() ? I + 1 : I); + } + /// Determine whether this function has a single parameter, or multiple /// parameters where all but the first have default arguments. /// @@ -2591,6 +2773,14 @@ public: FunctionDeclBits.IsInline = I; } + /// Determine whether the function was declared in source context + /// that requires constrained FP intrinsics + bool UsesFPIntrin() const { return FunctionDeclBits.UsesFPIntrin; } + + /// Set whether the function was declared in source context + /// that requires constrained FP intrinsics + void setUsesFPIntrin(bool I) { FunctionDeclBits.UsesFPIntrin = I; } + /// Flag that this function is implicitly inline. void setImplicitlyInline(bool I = true) { FunctionDeclBits.IsInline = I; } @@ -2655,6 +2845,13 @@ public: setInstantiationOfMemberFunction(getASTContext(), FD, TSK); } + /// Specify that this function declaration was instantiated from a + /// FunctionDecl FD. This is only used if this is a function declaration + /// declared locally inside of a function template. + void setInstantiatedFromDecl(FunctionDecl *FD); + + FunctionDecl *getInstantiatedFromDecl() const; + /// Retrieves the function template that is described by this /// function declaration. /// @@ -2673,9 +2870,7 @@ public: /// Determine whether this function is a function template /// specialization. - bool isFunctionTemplateSpecialization() const { - return getPrimaryTemplate() != nullptr; - } + bool isFunctionTemplateSpecialization() const; /// If this function is actually a function template specialization, /// retrieve information about this function template specialization. @@ -2758,9 +2953,9 @@ public: /// Specifies that this function declaration is actually a /// dependent function template specialization. - void setDependentTemplateSpecialization(ASTContext &Context, - const UnresolvedSetImpl &Templates, - const TemplateArgumentListInfo &TemplateArgs); + void setDependentTemplateSpecialization( + ASTContext &Context, const UnresolvedSetImpl &Templates, + const TemplateArgumentListInfo *TemplateArgs); DependentFunctionTemplateSpecializationInfo * getDependentSpecializationInfo() const; @@ -2820,11 +3015,7 @@ public: /// Represents a member of a struct/union/class. class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> { - unsigned BitField : 1; - unsigned Mutable : 1; - mutable unsigned CachedFieldIndex : 30; - - /// The kinds of value we can store in InitializerOrBitWidth. + /// The kinds of value we can store in StorageKind. /// /// Note that this is compatible with InClassInitStyle except for /// ISK_CapturedVLAType. @@ -2847,10 +3038,18 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> { ISK_CapturedVLAType, }; + LLVM_PREFERRED_TYPE(bool) + unsigned BitField : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned Mutable : 1; + LLVM_PREFERRED_TYPE(InitStorageKind) + unsigned StorageKind : 2; + mutable unsigned CachedFieldIndex : 28; + /// If this is a bitfield with a default member initializer, this /// structure is used to represent the two expressions. - struct InitAndBitWidth { - Expr *Init; + struct InitAndBitWidthStorage { + LazyDeclStmtPtr Init; Expr *BitWidth; }; @@ -2863,16 +3062,25 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> { /// and attached. // FIXME: Tail-allocate this to reduce the size of FieldDecl in the // overwhelmingly common case that we have none of these things. - llvm::PointerIntPair<void *, 2, InitStorageKind> InitStorage; + union { + // Active member if ISK is not ISK_CapturedVLAType and BitField is false. + LazyDeclStmtPtr Init; + // Active member if ISK is ISK_NoInit and BitField is true. + Expr *BitWidth; + // Active member if ISK is ISK_InClass*Init and BitField is true. + InitAndBitWidthStorage *InitAndBitWidth; + // Active member if ISK is ISK_CapturedVLAType. + const VariableArrayType *CapturedVLAType; + }; protected: FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, + TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle) - : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), - BitField(false), Mutable(Mutable), CachedFieldIndex(0), - InitStorage(nullptr, (InitStorageKind) InitStyle) { + : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), BitField(false), + Mutable(Mutable), StorageKind((InitStorageKind)InitStyle), + CachedFieldIndex(0), Init() { if (BW) setBitWidth(BW); } @@ -2908,15 +3116,16 @@ public: /// store the data for the anonymous union or struct. bool isAnonymousStructOrUnion() const; + /// Returns the expression that represents the bit width, if this field + /// is a bit field. For non-bitfields, this returns \c nullptr. Expr *getBitWidth() const { if (!BitField) return nullptr; - void *Ptr = InitStorage.getPointer(); - if (getInClassInitStyle()) - return static_cast<InitAndBitWidth*>(Ptr)->BitWidth; - return static_cast<Expr*>(Ptr); + return hasInClassInitializer() ? InitAndBitWidth->BitWidth : BitWidth; } + /// Computes the bit width of this field, if this is a bit field. + /// May not be called on non-bitfields. unsigned getBitWidthValue(const ASTContext &Ctx) const; /// Set the bit-field width for this member. @@ -2925,11 +3134,11 @@ public: assert(!hasCapturedVLAType() && !BitField && "bit width or captured type already set"); assert(Width && "no bit width specified"); - InitStorage.setPointer( - InitStorage.getInt() - ? new (getASTContext()) - InitAndBitWidth{getInClassInitializer(), Width} - : static_cast<void*>(Width)); + if (hasInClassInitializer()) + InitAndBitWidth = + new (getASTContext()) InitAndBitWidthStorage{Init, Width}; + else + BitWidth = Width; BitField = true; } @@ -2937,7 +3146,11 @@ public: // Note: used by some clients (i.e., do not remove it). void removeBitWidth() { assert(isBitField() && "no bitfield width to remove"); - InitStorage.setPointer(getInClassInitializer()); + if (hasInClassInitializer()) { + // Read the old initializer before we change the active union member. + auto ExistingInit = InitAndBitWidth->Init; + Init = ExistingInit; + } BitField = false; } @@ -2951,11 +3164,14 @@ public: /// [[no_unique_address]] attribute. bool isZeroSize(const ASTContext &Ctx) const; + /// Determine if this field is of potentially-overlapping class type, that + /// is, subobject with the [[no_unique_address]] attribute + bool isPotentiallyOverlapping() const; + /// Get the kind of (C++11) default member initializer that this field has. InClassInitStyle getInClassInitStyle() const { - InitStorageKind storageKind = InitStorage.getInt(); - return (storageKind == ISK_CapturedVLAType - ? ICIS_NoInit : (InClassInitStyle) storageKind); + return (StorageKind == ISK_CapturedVLAType ? ICIS_NoInit + : (InClassInitStyle)StorageKind); } /// Determine whether this member has a C++11 default member initializer. @@ -2963,44 +3179,44 @@ public: return getInClassInitStyle() != ICIS_NoInit; } + /// Determine whether getInClassInitializer() would return a non-null pointer + /// without deserializing the initializer. + bool hasNonNullInClassInitializer() const { + return hasInClassInitializer() && (BitField ? InitAndBitWidth->Init : Init); + } + /// Get the C++11 default member initializer for this member, or null if one /// has not been set. If a valid declaration has a default member initializer, /// but this returns null, then we have not parsed and attached it yet. - Expr *getInClassInitializer() const { - if (!hasInClassInitializer()) - return nullptr; - void *Ptr = InitStorage.getPointer(); - if (BitField) - return static_cast<InitAndBitWidth*>(Ptr)->Init; - return static_cast<Expr*>(Ptr); - } + Expr *getInClassInitializer() const; /// Set the C++11 in-class initializer for this member. - void setInClassInitializer(Expr *Init) { - assert(hasInClassInitializer() && !getInClassInitializer()); - if (BitField) - static_cast<InitAndBitWidth*>(InitStorage.getPointer())->Init = Init; - else - InitStorage.setPointer(Init); - } + void setInClassInitializer(Expr *NewInit); +private: + void setLazyInClassInitializer(LazyDeclStmtPtr NewInit); + +public: /// Remove the C++11 in-class initializer from this member. void removeInClassInitializer() { assert(hasInClassInitializer() && "no initializer to remove"); - InitStorage.setPointerAndInt(getBitWidth(), ISK_NoInit); + StorageKind = ISK_NoInit; + if (BitField) { + // Read the bit width before we change the active union member. + Expr *ExistingBitWidth = InitAndBitWidth->BitWidth; + BitWidth = ExistingBitWidth; + } } /// Determine whether this member captures the variable length array /// type. bool hasCapturedVLAType() const { - return InitStorage.getInt() == ISK_CapturedVLAType; + return StorageKind == ISK_CapturedVLAType; } /// Get the captured variable length array type. const VariableArrayType *getCapturedVLAType() const { - return hasCapturedVLAType() ? static_cast<const VariableArrayType *>( - InitStorage.getPointer()) - : nullptr; + return hasCapturedVLAType() ? CapturedVLAType : nullptr; } /// Set the captured variable length array type for this field. @@ -3028,21 +3244,24 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstField && K <= lastField; } + + void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override; }; /// An instance of this object exists for each enum constant /// that is defined. For example, in "enum X {a,b}", each of a/b are /// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a /// TagType for the X EnumDecl. -class EnumConstantDecl : public ValueDecl, public Mergeable<EnumConstantDecl> { +class EnumConstantDecl : public ValueDecl, + public Mergeable<EnumConstantDecl>, + public APIntStorage { Stmt *Init; // an integer constant expression - llvm::APSInt Val; // The value. + bool IsUnsigned; protected: - EnumConstantDecl(DeclContext *DC, SourceLocation L, + EnumConstantDecl(const ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E, - const llvm::APSInt &V) - : ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {} + const llvm::APSInt &V); public: friend class StmtIteratorBase; @@ -3055,10 +3274,15 @@ public: const Expr *getInitExpr() const { return (const Expr*) Init; } Expr *getInitExpr() { return (Expr*) Init; } - const llvm::APSInt &getInitVal() const { return Val; } + llvm::APSInt getInitVal() const { + return llvm::APSInt(getValue(), IsUnsigned); + } void setInitExpr(Expr *E) { Init = (Stmt*) E; } - void setInitVal(const llvm::APSInt &V) { Val = V; } + void setInitVal(const ASTContext &C, const llvm::APSInt &V) { + setValue(C, V); + IsUnsigned = V.isUnsigned(); + } SourceRange getSourceRange() const override LLVM_READONLY; @@ -3096,7 +3320,7 @@ public: using chain_iterator = ArrayRef<NamedDecl *>::const_iterator; ArrayRef<NamedDecl *> chain() const { - return llvm::makeArrayRef(Chaining, ChainingSize); + return llvm::ArrayRef(Chaining, ChainingSize); } chain_iterator chain_begin() const { return chain().begin(); } chain_iterator chain_end() const { return chain().end(); } @@ -3470,6 +3694,24 @@ public: /// parameters. bool isDependentType() const { return isDependentContext(); } + /// Whether this declaration was a definition in some module but was forced + /// to be a declaration. + /// + /// Useful for clients checking if a module has a definition of a specific + /// symbol and not interested in the final AST with deduplicated definitions. + bool isThisDeclarationADemotedDefinition() const { + return TagDeclBits.IsThisDeclarationADemotedDefinition; + } + + /// Mark a definition as a declaration and maintain information it _was_ + /// a definition. + void demoteThisDefinitionToDeclaration() { + assert(isCompleteDefinition() && + "Should demote definitions only, not forward declarations"); + setCompleteDefinition(false); + TagDeclBits.IsThisDeclarationADemotedDefinition = true; + } + /// Starts the definition of this tag declaration. /// /// This method should be invoked at the beginning of the definition @@ -3495,13 +3737,15 @@ public: return static_cast<TagKind>(TagDeclBits.TagDeclKind); } - void setTagKind(TagKind TK) { TagDeclBits.TagDeclKind = TK; } + void setTagKind(TagKind TK) { + TagDeclBits.TagDeclKind = llvm::to_underlying(TK); + } - bool isStruct() const { return getTagKind() == TTK_Struct; } - bool isInterface() const { return getTagKind() == TTK_Interface; } - bool isClass() const { return getTagKind() == TTK_Class; } - bool isUnion() const { return getTagKind() == TTK_Union; } - bool isEnum() const { return getTagKind() == TTK_Enum; } + bool isStruct() const { return getTagKind() == TagTypeKind::Struct; } + bool isInterface() const { return getTagKind() == TagTypeKind::Interface; } + bool isClass() const { return getTagKind() == TagTypeKind::Class; } + bool isUnion() const { return getTagKind() == TagTypeKind::Union; } + bool isEnum() const { return getTagKind() == TagTypeKind::Enum; } /// Is this tag type named, either directly or via being defined in /// a typedef of this type? @@ -3555,6 +3799,9 @@ public: return getExtInfo()->TemplParamLists[i]; } + using TypeDecl::printName; + void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override; + void setTemplateParameterListsInfo(ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists); @@ -3688,6 +3935,10 @@ public: bool IsFixed); static EnumDecl *CreateDeserialized(ASTContext &C, unsigned ID); + /// Overrides to provide correct range when there's an enum-base specifier + /// with forward declarations. + SourceRange getSourceRange() const override LLVM_READONLY; + /// When created, the EnumDecl corresponds to a /// forward-declared enum. This method is used to mark the /// declaration as being defined; its enumerators have already been @@ -3769,6 +4020,11 @@ public: /// -101 1001011 8 unsigned getNumNegativeBits() const { return EnumDeclBits.NumNegativeBits; } + /// Calculates the [Min,Max) values the enum can store based on the + /// NumPositiveBits and NumNegativeBits. This matters for enums that do not + /// have a fixed underlying type. + void getValueRange(llvm::APInt &Max, llvm::APInt &Min) const; + /// Returns true if this is a C++11 scoped enumeration. bool isScoped() const { return EnumDeclBits.IsScoped; } @@ -3839,6 +4095,29 @@ public: static bool classofKind(Kind K) { return K == Enum; } }; +/// Enum that represents the different ways arguments are passed to and +/// returned from function calls. This takes into account the target-specific +/// and version-specific rules along with the rules determined by the +/// language. +enum class RecordArgPassingKind { + /// The argument of this type can be passed directly in registers. + CanPassInRegs, + + /// The argument of this type cannot be passed directly in registers. + /// Records containing this type as a subobject are not forced to be passed + /// indirectly. This value is used only in C++. This value is required by + /// C++ because, in uncommon situations, it is possible for a class to have + /// only trivial copy/move constructors even when one of its subobjects has + /// a non-trivial copy/move constructor (if e.g. the corresponding copy/move + /// constructor in the derived class is deleted). + CannotPassInRegs, + + /// The argument of this type cannot be passed directly in registers. + /// Records containing this type as a subobject are forced to be passed + /// indirectly. + CanNeverPassInRegs +}; + /// Represents a struct/union/class. For example: /// struct X; // Forward declaration, no "body". /// union Y { int A, B; }; // Has body with members A and B (FieldDecls). @@ -3848,28 +4127,7 @@ class RecordDecl : public TagDecl { // to save some space. Use the provided accessors to access it. public: friend class DeclContext; - /// Enum that represents the different ways arguments are passed to and - /// returned from function calls. This takes into account the target-specific - /// and version-specific rules along with the rules determined by the - /// language. - enum ArgPassingKind : unsigned { - /// The argument of this type can be passed directly in registers. - APK_CanPassInRegs, - - /// The argument of this type cannot be passed directly in registers. - /// Records containing this type as a subobject are not forced to be passed - /// indirectly. This value is used only in C++. This value is required by - /// C++ because, in uncommon situations, it is possible for a class to have - /// only trivial copy/move constructors even when one of its subobjects has - /// a non-trivial copy/move constructor (if e.g. the corresponding copy/move - /// constructor in the derived class is deleted). - APK_CannotPassInRegs, - - /// The argument of this type cannot be passed directly in registers. - /// Records containing this type as a subobject are forced to be passed - /// indirectly. - APK_CanNeverPassInRegs - }; + friend class ASTDeclReader; protected: RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, @@ -3994,15 +4252,16 @@ public: /// it must have at least one trivial, non-deleted copy or move constructor. /// FIXME: This should be set as part of completeDefinition. bool canPassInRegisters() const { - return getArgPassingRestrictions() == APK_CanPassInRegs; + return getArgPassingRestrictions() == RecordArgPassingKind::CanPassInRegs; } - ArgPassingKind getArgPassingRestrictions() const { - return static_cast<ArgPassingKind>(RecordDeclBits.ArgPassingRestrictions); + RecordArgPassingKind getArgPassingRestrictions() const { + return static_cast<RecordArgPassingKind>( + RecordDeclBits.ArgPassingRestrictions); } - void setArgPassingRestrictions(ArgPassingKind Kind) { - RecordDeclBits.ArgPassingRestrictions = Kind; + void setArgPassingRestrictions(RecordArgPassingKind Kind) { + RecordDeclBits.ArgPassingRestrictions = llvm::to_underlying(Kind); } bool isParamDestroyedInCallee() const { @@ -4013,6 +4272,12 @@ public: RecordDeclBits.ParamDestroyedInCallee = V; } + bool isRandomized() const { return RecordDeclBits.IsRandomized; } + + void setIsRandomized(bool V) { RecordDeclBits.IsRandomized = V; } + + void reorderDecls(const SmallVectorImpl<Decl *> &Decls); + /// Determines whether this declaration represents the /// injected class name. /// @@ -4097,9 +4362,16 @@ public: /// nullptr is returned if no named data member exists. const FieldDecl *findFirstNamedDataMember() const; + /// Get precomputed ODRHash or add a new one. + unsigned getODRHash(); + private: /// Deserialize just the fields. void LoadFieldsFromExternalStorage() const; + + /// True if a valid hash is stored in ODRHash. + bool hasODRHash() const { return RecordDeclBits.ODRHash; } + void setODRHash(unsigned Hash) { RecordDeclBits.ODRHash = Hash; } }; class FileScopeAsmDecl : public Decl { @@ -4134,6 +4406,41 @@ public: static bool classofKind(Kind K) { return K == FileScopeAsm; } }; +/// A declaration that models statements at global scope. This declaration +/// supports incremental and interactive C/C++. +/// +/// \note This is used in libInterpreter, clang -cc1 -fincremental-extensions +/// and in tools such as clang-repl. +class TopLevelStmtDecl : public Decl { + friend class ASTDeclReader; + friend class ASTDeclWriter; + + Stmt *Statement = nullptr; + bool IsSemiMissing = false; + + TopLevelStmtDecl(DeclContext *DC, SourceLocation L, Stmt *S) + : Decl(TopLevelStmt, DC, L), Statement(S) {} + + virtual void anchor(); + +public: + static TopLevelStmtDecl *Create(ASTContext &C, Stmt *Statement); + static TopLevelStmtDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + SourceRange getSourceRange() const override LLVM_READONLY; + Stmt *getStmt() { return Statement; } + const Stmt *getStmt() const { return Statement; } + void setStmt(Stmt *S) { + assert(IsSemiMissing && "Operation supported for printing values only!"); + Statement = S; + } + bool isSemiMissing() const { return IsSemiMissing; } + void setSemiMissing(bool Missing = true) { IsSemiMissing = Missing; } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == TopLevelStmt; } +}; + /// Represents a block literal declaration, which is like an /// unnamed FunctionDecl. For example: /// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } @@ -4429,6 +4736,16 @@ public: /// @import std.vector; /// \endcode /// +/// A C++20 module import declaration imports the named module or partition. +/// Periods are permitted in C++20 module names, but have no semantic meaning. +/// For example: +/// \code +/// import NamedModule; +/// import :SomePartition; // Must be a partition of the current module. +/// import Names.Like.this; // Allowed. +/// import :and.Also.Partition.names; +/// \endcode +/// /// Import declarations can also be implicitly generated from /// \#include/\#import directives. class ImportDecl final : public Decl, @@ -4505,7 +4822,7 @@ public: static bool classofKind(Kind K) { return K == Import; } }; -/// Represents a C++ Modules TS module export declaration. +/// Represents a standard C++ module export declaration. /// /// For example: /// \code @@ -4572,11 +4889,56 @@ public: static bool classofKind(Kind K) { return K == Empty; } }; +/// HLSLBufferDecl - Represent a cbuffer or tbuffer declaration. +class HLSLBufferDecl final : public NamedDecl, public DeclContext { + /// LBraceLoc - The ending location of the source range. + SourceLocation LBraceLoc; + /// RBraceLoc - The ending location of the source range. + SourceLocation RBraceLoc; + /// KwLoc - The location of the cbuffer or tbuffer keyword. + SourceLocation KwLoc; + /// IsCBuffer - Whether the buffer is a cbuffer (and not a tbuffer). + bool IsCBuffer; + + HLSLBufferDecl(DeclContext *DC, bool CBuffer, SourceLocation KwLoc, + IdentifierInfo *ID, SourceLocation IDLoc, + SourceLocation LBrace); + +public: + static HLSLBufferDecl *Create(ASTContext &C, DeclContext *LexicalParent, + bool CBuffer, SourceLocation KwLoc, + IdentifierInfo *ID, SourceLocation IDLoc, + SourceLocation LBrace); + static HLSLBufferDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + SourceRange getSourceRange() const override LLVM_READONLY { + return SourceRange(getLocStart(), RBraceLoc); + } + SourceLocation getLocStart() const LLVM_READONLY { return KwLoc; } + SourceLocation getLBraceLoc() const { return LBraceLoc; } + SourceLocation getRBraceLoc() const { return RBraceLoc; } + void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } + bool isCBuffer() const { return IsCBuffer; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == HLSLBuffer; } + static DeclContext *castToDeclContext(const HLSLBufferDecl *D) { + return static_cast<DeclContext *>(const_cast<HLSLBufferDecl *>(D)); + } + static HLSLBufferDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<HLSLBufferDecl *>(const_cast<DeclContext *>(DC)); + } + + friend class ASTDeclReader; + friend class ASTDeclWriter; +}; + /// Insertion operator for diagnostics. This allows sending NamedDecl's /// into a diagnostic with <<. inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD, const NamedDecl *ND) { - PD.AddTaggedVal(reinterpret_cast<intptr_t>(ND), + PD.AddTaggedVal(reinterpret_cast<uint64_t>(ND), DiagnosticsEngine::ak_nameddecl); return PD; } diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclBase.h b/contrib/llvm-project/clang/include/clang/AST/DeclBase.h index 482d2889a25a..eb7a1a320600 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclBase.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclBase.h @@ -16,8 +16,10 @@ #include "clang/AST/ASTDumperUtils.h" #include "clang/AST/AttrIterator.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/SelectorLocationsKind.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/ArrayRef.h" @@ -48,18 +50,12 @@ class ExternalSourceSymbolAttr; class FunctionDecl; class FunctionType; class IdentifierInfo; -enum Linkage : unsigned char; +enum class Linkage : unsigned char; class LinkageSpecDecl; class Module; class NamedDecl; -class ObjCCategoryDecl; -class ObjCCategoryImplDecl; class ObjCContainerDecl; -class ObjCImplDecl; -class ObjCImplementationDecl; -class ObjCInterfaceDecl; class ObjCMethodDecl; -class ObjCProtocolDecl; struct PrintingPolicy; class RecordDecl; class SourceManager; @@ -216,7 +212,7 @@ public: /// The kind of ownership a declaration has, for visibility purposes. /// This enumeration is designed such that higher values represent higher /// levels of name hiding. - enum class ModuleOwnershipKind : unsigned { + enum class ModuleOwnershipKind : unsigned char { /// This declaration is not owned by a module. Unowned, @@ -231,8 +227,15 @@ public: /// module is imported. VisibleWhenImported, + /// This declaration has an owning module, and is visible to lookups + /// that occurs within that module. And it is reachable in other module + /// when the owning module is transitively imported. + ReachableWhenImported, + /// This declaration has an owning module, but is only visible to /// lookups that occur within that module. + /// The discarded declarations in global module fragment belongs + /// to this group too. ModulePrivate }; @@ -241,8 +244,8 @@ protected: /// DeclContext. These pointers form the linked list that is /// traversed via DeclContext's decls_begin()/decls_end(). /// - /// The extra two bits are used for the ModuleOwnershipKind. - llvm::PointerIntPair<Decl *, 2, ModuleOwnershipKind> NextInContextAndBits; + /// The extra three bits are used for the ModuleOwnershipKind. + llvm::PointerIntPair<Decl *, 3, ModuleOwnershipKind> NextInContextAndBits; private: friend class DeclContext; @@ -282,31 +285,38 @@ private: SourceLocation Loc; /// DeclKind - This indicates which class this is. + LLVM_PREFERRED_TYPE(Kind) unsigned DeclKind : 7; /// InvalidDecl - This indicates a semantic error occurred. + LLVM_PREFERRED_TYPE(bool) unsigned InvalidDecl : 1; /// HasAttrs - This indicates whether the decl has attributes or not. + LLVM_PREFERRED_TYPE(bool) unsigned HasAttrs : 1; /// Implicit - Whether this declaration was implicitly generated by /// the implementation rather than explicitly written by the user. + LLVM_PREFERRED_TYPE(bool) unsigned Implicit : 1; /// Whether this declaration was "used", meaning that a definition is /// required. + LLVM_PREFERRED_TYPE(bool) unsigned Used : 1; /// Whether this declaration was "referenced". /// The difference with 'Used' is whether the reference appears in a /// evaluated context or not, e.g. functions used in uninstantiated templates /// are regarded as "referenced" but not "used". + LLVM_PREFERRED_TYPE(bool) unsigned Referenced : 1; /// Whether this declaration is a top-level declaration (function, /// global variable, etc.) that is lexically inside an objc container /// definition. + LLVM_PREFERRED_TYPE(bool) unsigned TopLevelDeclInObjCContainer : 1; /// Whether statistic collection is enabled. @@ -319,20 +329,24 @@ protected: friend class ASTReader; friend class CXXClassMemberWrapper; friend class LinkageComputer; + friend class RecordDecl; template<typename decl_type> friend class Redeclarable; /// Access - Used by C++ decls for the access specifier. // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum + LLVM_PREFERRED_TYPE(AccessSpecifier) unsigned Access : 2; /// Whether this declaration was loaded from an AST file. + LLVM_PREFERRED_TYPE(bool) unsigned FromASTFile : 1; /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. + LLVM_PREFERRED_TYPE(IdentifierNamespace) unsigned IdentifierNamespace : 14; /// If 0, we have not computed the linkage of this declaration. - /// Otherwise, it is the linkage + 1. + LLVM_PREFERRED_TYPE(Linkage) mutable unsigned CacheValidAndLinkage : 3; /// Allocate memory for a deserialized declaration. @@ -352,7 +366,7 @@ protected: DeclContext *Parent, std::size_t Extra = 0); private: - bool AccessDeclContextSanity() const; + bool AccessDeclContextCheck() const; /// Get the module ownership kind to use for a local lexical child of \p DC, /// which may be either a local or (rarely) an imported declaration. @@ -383,7 +397,7 @@ protected: Implicit(false), Used(false), Referenced(false), TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - CacheValidAndLinkage(0) { + CacheValidAndLinkage(llvm::to_underlying(Linkage::Invalid)) { if (StatisticsEnabled) add(DK); } @@ -392,7 +406,7 @@ protected: Used(false), Referenced(false), TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - CacheValidAndLinkage(0) { + CacheValidAndLinkage(llvm::to_underlying(Linkage::Invalid)) { if (StatisticsEnabled) add(DK); } @@ -402,11 +416,11 @@ protected: void updateOutOfDate(IdentifierInfo &II) const; Linkage getCachedLinkage() const { - return Linkage(CacheValidAndLinkage - 1); + return static_cast<Linkage>(CacheValidAndLinkage); } void setCachedLinkage(Linkage L) const { - CacheValidAndLinkage = L + 1; + CacheValidAndLinkage = llvm::to_underlying(L); } bool hasCachedLinkage() const { @@ -445,6 +459,14 @@ public: return const_cast<Decl*>(this)->getDeclContext(); } + /// Return the non transparent context. + /// See the comment of `DeclContext::isTransparentContext()` for the + /// definition of transparent context. + DeclContext *getNonTransparentDeclContext(); + const DeclContext *getNonTransparentDeclContext() const { + return const_cast<Decl *>(this)->getNonTransparentDeclContext(); + } + /// Find the innermost non-closure ancestor of this declaration, /// walking up through blocks, lambdas, etc. If that ancestor is /// not a code context (!isFunctionOrMethod()), returns null. @@ -464,6 +486,18 @@ public: bool isInStdNamespace() const; + // Return true if this is a FileContext Decl. + bool isFileContextDecl() const; + + /// Whether it resembles a flexible array member. This is a static member + /// because we want to be able to call it with a nullptr. That allows us to + /// perform non-Decl specific checks based on the object's type and strict + /// flex array level. + static bool isFlexibleArrayMemberLike( + ASTContext &Context, const Decl *D, QualType Ty, + LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel, + bool IgnoreTemplateOrMacroSubstitution); + ASTContext &getASTContext() const LLVM_READONLY; /// Helper to get the language options from the ASTContext. @@ -472,11 +506,11 @@ public: void setAccess(AccessSpecifier AS) { Access = AS; - assert(AccessDeclContextSanity()); + assert(AccessDeclContextCheck()); } AccessSpecifier getAccess() const { - assert(AccessDeclContextSanity()); + assert(AccessDeclContextCheck()); return AccessSpecifier(Access); } @@ -514,17 +548,18 @@ public: return hasAttrs() ? getAttrs().end() : nullptr; } - template <typename T> - void dropAttr() { + template <typename... Ts> void dropAttrs() { if (!HasAttrs) return; AttrVec &Vec = getAttrs(); - llvm::erase_if(Vec, [](Attr *A) { return isa<T>(A); }); + llvm::erase_if(Vec, [](Attr *A) { return isa<Ts...>(A); }); if (Vec.empty()) HasAttrs = false; } + template <typename T> void dropAttr() { dropAttrs<T>(); } + template <typename T> llvm::iterator_range<specific_attr_iterator<T>> specific_attrs() const { return llvm::make_range(specific_attr_begin<T>(), specific_attr_end<T>()); @@ -613,6 +648,41 @@ public: return getModuleOwnershipKind() == ModuleOwnershipKind::ModulePrivate; } + /// Whether this declaration was exported in a lexical context. + /// e.g.: + /// + /// export namespace A { + /// void f1(); // isInExportDeclContext() == true + /// } + /// void A::f1(); // isInExportDeclContext() == false + /// + /// namespace B { + /// void f2(); // isInExportDeclContext() == false + /// } + /// export void B::f2(); // isInExportDeclContext() == true + bool isInExportDeclContext() const; + + bool isInvisibleOutsideTheOwningModule() const { + return getModuleOwnershipKind() > ModuleOwnershipKind::VisibleWhenImported; + } + + /// Whether this declaration comes from another module unit. + bool isInAnotherModuleUnit() const; + + /// FIXME: Implement discarding declarations actually in global module + /// fragment. See [module.global.frag]p3,4 for details. + bool isDiscardedInGlobalModuleFragment() const { return false; } + + /// Check if we should skip checking ODRHash for declaration \param D. + /// + /// The existing ODRHash mechanism seems to be not stable enough and + /// the false positive ODR violation reports are annoying and we rarely see + /// true ODR violation reports. Also we learned that MSVC disabled ODR checks + /// for declarations in GMF. So we try to disable ODR checks in the GMF to + /// get better user experiences before we make the ODR violation checks stable + /// enough. + bool shouldSkipCheckingODR() const; + /// Return true if this declaration has an attribute which acts as /// definition of the entity, such as 'alias' or 'ifunc'. bool hasDefiningAttr() const; @@ -775,7 +845,7 @@ public: } /// Get the module that owns this declaration for linkage purposes. - /// There only ever is such a module under the C++ Modules TS. + /// There only ever is such a standard C++ module. /// /// \param IgnoreLinkage Ignore the linkage of the entity; assume that /// all declarations in a global module fragment are unowned. @@ -790,6 +860,11 @@ public: return (int)getModuleOwnershipKind() <= (int)ModuleOwnershipKind::Visible; } + bool isReachable() const { + return (int)getModuleOwnershipKind() <= + (int)ModuleOwnershipKind::ReachableWhenImported; + } + /// Set that this declaration is globally visible, even if it came from a /// module that is not visible. void setVisibleDespiteOwningModule() { @@ -891,10 +966,12 @@ public: /// If this decl is defined inside a function/method/block it returns /// the corresponding DeclContext, otherwise it returns null. - const DeclContext *getParentFunctionOrMethod() const; - DeclContext *getParentFunctionOrMethod() { - return const_cast<DeclContext*>( - const_cast<const Decl*>(this)->getParentFunctionOrMethod()); + const DeclContext * + getParentFunctionOrMethod(bool LexicalParent = false) const; + DeclContext *getParentFunctionOrMethod(bool LexicalParent = false) { + return const_cast<DeclContext *>( + const_cast<const Decl *>(this)->getParentFunctionOrMethod( + LexicalParent)); } /// Retrieves the "canonical" declaration of the given declaration. @@ -1089,7 +1166,7 @@ public: /// Determine whether this is a block-scope declaration with linkage. /// This will either be a local variable declaration declared 'extern', or a /// local function declaration. - bool isLocalExternDecl() { + bool isLocalExternDecl() const { return IdentifierNamespace & IDNS_LocalExtern; } @@ -1130,6 +1207,12 @@ public: } } + /// Clears the namespace of this declaration. + /// + /// This is useful if we want this declaration to be available for + /// redeclaration lookup but otherwise hidden for ordinary name lookups. + void clearIdentifierNamespace() { IdentifierNamespace = 0; } + enum FriendObjectKind { FOK_None, ///< Not a friend object. FOK_Declared, ///< A friend of a previously-declared entity. @@ -1185,6 +1268,10 @@ public: /// have a FunctionType. const FunctionType *getFunctionType(bool BlocksToo = true) const; + // Looks through the Decl's underlying type to determine if it's a + // function pointer type. + bool isFunctionPointerType() const; + private: void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx); void setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC, @@ -1327,6 +1414,18 @@ public: } }; +/// Only used by CXXDeductionGuideDecl. +enum class DeductionCandidate : unsigned char { + Normal, + Copy, + Aggregate, +}; + +enum class RecordArgPassingKind; +enum class OMPDeclareReductionInitKind; +enum class ObjCImplementationControl; +enum class LinkageSpecLanguageIDs; + /// DeclContext - This is used only as base class of specific decl types that /// can act as declaration contexts. These decls are (only the top classes /// that directly derive from DeclContext are mentioned, not their subclasses): @@ -1347,6 +1446,8 @@ public: class DeclContext { /// For makeDeclVisibleInContextImpl friend class ASTDeclReader; + /// For checking the new bits in the Serialization part. + friend class ASTDeclWriter; /// For reconcileExternalVisibleStorage, CreateStoredDeclsMap, /// hasNeedToReconcileExternalVisibleStorage friend class ExternalASTSource; @@ -1365,35 +1466,42 @@ class DeclContext { class DeclContextBitfields { friend class DeclContext; /// DeclKind - This indicates which class this is. + LLVM_PREFERRED_TYPE(Decl::Kind) uint64_t DeclKind : 7; /// Whether this declaration context also has some external /// storage that contains additional declarations that are lexically /// part of this context. + LLVM_PREFERRED_TYPE(bool) mutable uint64_t ExternalLexicalStorage : 1; /// Whether this declaration context also has some external /// storage that contains additional declarations that are visible /// in this context. + LLVM_PREFERRED_TYPE(bool) mutable uint64_t ExternalVisibleStorage : 1; /// Whether this declaration context has had externally visible /// storage added since the last lookup. In this case, \c LookupPtr's /// invariant may not hold and needs to be fixed before we perform /// another lookup. + LLVM_PREFERRED_TYPE(bool) mutable uint64_t NeedToReconcileExternalVisibleStorage : 1; /// If \c true, this context may have local lexical declarations /// that are missing from the lookup table. + LLVM_PREFERRED_TYPE(bool) mutable uint64_t HasLazyLocalLexicalLookups : 1; /// If \c true, the external source may have lexical declarations /// that are missing from the lookup table. + LLVM_PREFERRED_TYPE(bool) mutable uint64_t HasLazyExternalLexicalLookups : 1; /// If \c true, lookups should only return identifier from /// DeclContext scope (for example TranslationUnit). Used in /// LookupQualifiedName() + LLVM_PREFERRED_TYPE(bool) mutable uint64_t UseQualifiedLookup : 1; }; @@ -1406,48 +1514,60 @@ class DeclContext { class TagDeclBitfields { friend class TagDecl; /// For the bits in DeclContextBitfields + LLVM_PREFERRED_TYPE(DeclContextBitfields) uint64_t : NumDeclContextBits; /// The TagKind enum. + LLVM_PREFERRED_TYPE(TagTypeKind) uint64_t TagDeclKind : 3; /// True if this is a definition ("struct foo {};"), false if it is a /// declaration ("struct foo;"). It is not considered a definition /// until the definition has been fully processed. + LLVM_PREFERRED_TYPE(bool) uint64_t IsCompleteDefinition : 1; /// True if this is currently being defined. + LLVM_PREFERRED_TYPE(bool) uint64_t IsBeingDefined : 1; /// True if this tag declaration is "embedded" (i.e., defined or declared /// for the very first time) in the syntax of a declarator. + LLVM_PREFERRED_TYPE(bool) uint64_t IsEmbeddedInDeclarator : 1; /// True if this tag is free standing, e.g. "struct foo;". + LLVM_PREFERRED_TYPE(bool) uint64_t IsFreeStanding : 1; /// Indicates whether it is possible for declarations of this kind /// to have an out-of-date definition. /// /// This option is only enabled when modules are enabled. + LLVM_PREFERRED_TYPE(bool) uint64_t MayHaveOutOfDateDef : 1; /// Has the full definition of this type been required by a use somewhere in /// the TU. + LLVM_PREFERRED_TYPE(bool) uint64_t IsCompleteDefinitionRequired : 1; + + /// Whether this tag is a definition which was demoted due to + /// a module merge. + LLVM_PREFERRED_TYPE(bool) + uint64_t IsThisDeclarationADemotedDefinition : 1; }; - /// Number of non-inherited bits in TagDeclBitfields. - enum { NumTagDeclBits = 9 }; + /// Number of inherited and non-inherited bits in TagDeclBitfields. + enum { NumTagDeclBits = NumDeclContextBits + 10 }; /// Stores the bits used by EnumDecl. /// If modified NumEnumDeclBit and the accessor /// methods in EnumDecl should be updated appropriately. class EnumDeclBitfields { friend class EnumDecl; - /// For the bits in DeclContextBitfields. - uint64_t : NumDeclContextBits; /// For the bits in TagDeclBitfields. + LLVM_PREFERRED_TYPE(TagDeclBitfields) uint64_t : NumTagDeclBits; /// Width in bits required to store all the non-negative @@ -1460,78 +1580,102 @@ class DeclContext { /// True if this tag declaration is a scoped enumeration. Only /// possible in C++11 mode. + LLVM_PREFERRED_TYPE(bool) uint64_t IsScoped : 1; /// If this tag declaration is a scoped enum, /// then this is true if the scoped enum was declared using the class /// tag, false if it was declared with the struct tag. No meaning is /// associated if this tag declaration is not a scoped enum. + LLVM_PREFERRED_TYPE(bool) uint64_t IsScopedUsingClassTag : 1; /// True if this is an enumeration with fixed underlying type. Only /// possible in C++11, Microsoft extensions, or Objective C mode. + LLVM_PREFERRED_TYPE(bool) uint64_t IsFixed : 1; /// True if a valid hash is stored in ODRHash. + LLVM_PREFERRED_TYPE(bool) uint64_t HasODRHash : 1; }; - /// Number of non-inherited bits in EnumDeclBitfields. - enum { NumEnumDeclBits = 20 }; + /// Number of inherited and non-inherited bits in EnumDeclBitfields. + enum { NumEnumDeclBits = NumTagDeclBits + 20 }; /// Stores the bits used by RecordDecl. /// If modified NumRecordDeclBits and the accessor /// methods in RecordDecl should be updated appropriately. class RecordDeclBitfields { friend class RecordDecl; - /// For the bits in DeclContextBitfields. - uint64_t : NumDeclContextBits; /// For the bits in TagDeclBitfields. + LLVM_PREFERRED_TYPE(TagDeclBitfields) uint64_t : NumTagDeclBits; /// This is true if this struct ends with a flexible /// array member (e.g. int X[]) or if this union contains a struct that does. /// If so, this cannot be contained in arrays or other structs as a member. + LLVM_PREFERRED_TYPE(bool) uint64_t HasFlexibleArrayMember : 1; /// Whether this is the type of an anonymous struct or union. + LLVM_PREFERRED_TYPE(bool) uint64_t AnonymousStructOrUnion : 1; /// This is true if this struct has at least one member /// containing an Objective-C object pointer type. + LLVM_PREFERRED_TYPE(bool) uint64_t HasObjectMember : 1; /// This is true if struct has at least one member of /// 'volatile' type. + LLVM_PREFERRED_TYPE(bool) uint64_t HasVolatileMember : 1; /// Whether the field declarations of this record have been loaded /// from external storage. To avoid unnecessary deserialization of /// methods/nested types we allow deserialization of just the fields /// when needed. + LLVM_PREFERRED_TYPE(bool) mutable uint64_t LoadedFieldsFromExternalStorage : 1; /// Basic properties of non-trivial C structs. + LLVM_PREFERRED_TYPE(bool) uint64_t NonTrivialToPrimitiveDefaultInitialize : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t NonTrivialToPrimitiveCopy : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t NonTrivialToPrimitiveDestroy : 1; /// The following bits indicate whether this is or contains a C union that /// is non-trivial to default-initialize, destruct, or copy. These bits /// imply the associated basic non-triviality predicates declared above. + LLVM_PREFERRED_TYPE(bool) uint64_t HasNonTrivialToPrimitiveDefaultInitializeCUnion : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t HasNonTrivialToPrimitiveDestructCUnion : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t HasNonTrivialToPrimitiveCopyCUnion : 1; /// Indicates whether this struct is destroyed in the callee. + LLVM_PREFERRED_TYPE(bool) uint64_t ParamDestroyedInCallee : 1; /// Represents the way this type is passed to a function. + LLVM_PREFERRED_TYPE(RecordArgPassingKind) uint64_t ArgPassingRestrictions : 2; + + /// Indicates whether this struct has had its field layout randomized. + LLVM_PREFERRED_TYPE(bool) + uint64_t IsRandomized : 1; + + /// True if a valid hash is stored in ODRHash. This should shave off some + /// extra storage and prevent CXXRecordDecl to store unused bits. + uint64_t ODRHash : 26; }; - /// Number of non-inherited bits in RecordDeclBitfields. - enum { NumRecordDeclBits = 14 }; + /// Number of inherited and non-inherited bits in RecordDeclBitfields. + enum { NumRecordDeclBits = NumTagDeclBits + 41 }; /// Stores the bits used by OMPDeclareReductionDecl. /// If modified NumOMPDeclareReductionDeclBits and the accessor @@ -1539,113 +1683,156 @@ class DeclContext { class OMPDeclareReductionDeclBitfields { friend class OMPDeclareReductionDecl; /// For the bits in DeclContextBitfields + LLVM_PREFERRED_TYPE(DeclContextBitfields) uint64_t : NumDeclContextBits; /// Kind of initializer, - /// function call or omp_priv<init_expr> initializtion. + /// function call or omp_priv<init_expr> initialization. + LLVM_PREFERRED_TYPE(OMPDeclareReductionInitKind) uint64_t InitializerKind : 2; }; - /// Number of non-inherited bits in OMPDeclareReductionDeclBitfields. - enum { NumOMPDeclareReductionDeclBits = 2 }; + /// Number of inherited and non-inherited bits in + /// OMPDeclareReductionDeclBitfields. + enum { NumOMPDeclareReductionDeclBits = NumDeclContextBits + 2 }; /// Stores the bits used by FunctionDecl. /// If modified NumFunctionDeclBits and the accessor /// methods in FunctionDecl and CXXDeductionGuideDecl - /// (for IsCopyDeductionCandidate) should be updated appropriately. + /// (for DeductionCandidateKind) should be updated appropriately. class FunctionDeclBitfields { friend class FunctionDecl; - /// For IsCopyDeductionCandidate + /// For DeductionCandidateKind friend class CXXDeductionGuideDecl; /// For the bits in DeclContextBitfields. + LLVM_PREFERRED_TYPE(DeclContextBitfields) uint64_t : NumDeclContextBits; + LLVM_PREFERRED_TYPE(StorageClass) uint64_t SClass : 3; + LLVM_PREFERRED_TYPE(bool) uint64_t IsInline : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t IsInlineSpecified : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t IsVirtualAsWritten : 1; - uint64_t IsPure : 1; + LLVM_PREFERRED_TYPE(bool) + uint64_t IsPureVirtual : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t HasInheritedPrototype : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t HasWrittenPrototype : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t IsDeleted : 1; /// Used by CXXMethodDecl + LLVM_PREFERRED_TYPE(bool) uint64_t IsTrivial : 1; /// This flag indicates whether this function is trivial for the purpose of /// calls. This is meaningful only when this function is a copy/move /// constructor or a destructor. + LLVM_PREFERRED_TYPE(bool) uint64_t IsTrivialForCall : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t IsDefaulted : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t IsExplicitlyDefaulted : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t HasDefaultedFunctionInfo : 1; + + /// For member functions of complete types, whether this is an ineligible + /// special member function or an unselected destructor. See + /// [class.mem.special]. + LLVM_PREFERRED_TYPE(bool) + uint64_t IsIneligibleOrNotSelected : 1; + + LLVM_PREFERRED_TYPE(bool) uint64_t HasImplicitReturnZero : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t IsLateTemplateParsed : 1; /// Kind of contexpr specifier as defined by ConstexprSpecKind. + LLVM_PREFERRED_TYPE(ConstexprSpecKind) uint64_t ConstexprKind : 2; + LLVM_PREFERRED_TYPE(bool) + uint64_t BodyContainsImmediateEscalatingExpression : 1; + + LLVM_PREFERRED_TYPE(bool) uint64_t InstantiationIsPending : 1; /// Indicates if the function uses __try. + LLVM_PREFERRED_TYPE(bool) uint64_t UsesSEHTry : 1; /// Indicates if the function was a definition /// but its body was skipped. + LLVM_PREFERRED_TYPE(bool) uint64_t HasSkippedBody : 1; /// Indicates if the function declaration will /// have a body, once we're done parsing it. + LLVM_PREFERRED_TYPE(bool) uint64_t WillHaveBody : 1; /// Indicates that this function is a multiversioned /// function using attribute 'target'. + LLVM_PREFERRED_TYPE(bool) uint64_t IsMultiVersion : 1; - /// [C++17] Only used by CXXDeductionGuideDecl. Indicates that - /// the Deduction Guide is the implicitly generated 'copy - /// deduction candidate' (is used during overload resolution). - uint64_t IsCopyDeductionCandidate : 1; + /// Only used by CXXDeductionGuideDecl. Indicates the kind + /// of the Deduction Guide that is implicitly generated + /// (used during overload resolution). + LLVM_PREFERRED_TYPE(DeductionCandidate) + uint64_t DeductionCandidateKind : 2; /// Store the ODRHash after first calculation. + LLVM_PREFERRED_TYPE(bool) uint64_t HasODRHash : 1; /// Indicates if the function uses Floating Point Constrained Intrinsics + LLVM_PREFERRED_TYPE(bool) uint64_t UsesFPIntrin : 1; + + // Indicates this function is a constrained friend, where the constraint + // refers to an enclosing template for hte purposes of [temp.friend]p9. + LLVM_PREFERRED_TYPE(bool) + uint64_t FriendConstraintRefersToEnclosingTemplate : 1; }; - /// Number of non-inherited bits in FunctionDeclBitfields. - enum { NumFunctionDeclBits = 27 }; + /// Number of inherited and non-inherited bits in FunctionDeclBitfields. + enum { NumFunctionDeclBits = NumDeclContextBits + 31 }; /// Stores the bits used by CXXConstructorDecl. If modified /// NumCXXConstructorDeclBits and the accessor /// methods in CXXConstructorDecl should be updated appropriately. class CXXConstructorDeclBitfields { friend class CXXConstructorDecl; - /// For the bits in DeclContextBitfields. - uint64_t : NumDeclContextBits; /// For the bits in FunctionDeclBitfields. + LLVM_PREFERRED_TYPE(FunctionDeclBitfields) uint64_t : NumFunctionDeclBits; - /// 24 bits to fit in the remaining available space. + /// 20 bits to fit in the remaining available space. /// Note that this makes CXXConstructorDeclBitfields take /// exactly 64 bits and thus the width of NumCtorInitializers /// will need to be shrunk if some bit is added to NumDeclContextBitfields, /// NumFunctionDeclBitfields or CXXConstructorDeclBitfields. - uint64_t NumCtorInitializers : 21; + uint64_t NumCtorInitializers : 17; + LLVM_PREFERRED_TYPE(bool) uint64_t IsInheritingConstructor : 1; /// Whether this constructor has a trail-allocated explicit specifier. + LLVM_PREFERRED_TYPE(bool) uint64_t HasTrailingExplicitSpecifier : 1; /// If this constructor does't have a trail-allocated explicit specifier. /// Whether this constructor is explicit specified. + LLVM_PREFERRED_TYPE(bool) uint64_t IsSimpleExplicit : 1; }; - /// Number of non-inherited bits in CXXConstructorDeclBitfields. - enum { - NumCXXConstructorDeclBits = 64 - NumDeclContextBits - NumFunctionDeclBits - }; + /// Number of inherited and non-inherited bits in CXXConstructorDeclBitfields. + enum { NumCXXConstructorDeclBits = NumFunctionDeclBits + 20 }; /// Stores the bits used by ObjCMethodDecl. /// If modified NumObjCMethodDeclBits and the accessor @@ -1654,43 +1841,56 @@ class DeclContext { friend class ObjCMethodDecl; /// For the bits in DeclContextBitfields. + LLVM_PREFERRED_TYPE(DeclContextBitfields) uint64_t : NumDeclContextBits; /// The conventional meaning of this method; an ObjCMethodFamily. /// This is not serialized; instead, it is computed on demand and /// cached. + LLVM_PREFERRED_TYPE(ObjCMethodFamily) mutable uint64_t Family : ObjCMethodFamilyBitWidth; /// instance (true) or class (false) method. + LLVM_PREFERRED_TYPE(bool) uint64_t IsInstance : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t IsVariadic : 1; /// True if this method is the getter or setter for an explicit property. + LLVM_PREFERRED_TYPE(bool) uint64_t IsPropertyAccessor : 1; /// True if this method is a synthesized property accessor stub. + LLVM_PREFERRED_TYPE(bool) uint64_t IsSynthesizedAccessorStub : 1; /// Method has a definition. + LLVM_PREFERRED_TYPE(bool) uint64_t IsDefined : 1; /// Method redeclaration in the same interface. + LLVM_PREFERRED_TYPE(bool) uint64_t IsRedeclaration : 1; /// Is redeclared in the same interface. + LLVM_PREFERRED_TYPE(bool) mutable uint64_t HasRedeclaration : 1; /// \@required/\@optional + LLVM_PREFERRED_TYPE(ObjCImplementationControl) uint64_t DeclImplementation : 2; /// in, inout, etc. + LLVM_PREFERRED_TYPE(Decl::ObjCDeclQualifier) uint64_t objcDeclQualifier : 7; /// Indicates whether this method has a related result type. + LLVM_PREFERRED_TYPE(bool) uint64_t RelatedResultType : 1; /// Whether the locations of the selector identifiers are in a /// "standard" position, a enum SelectorLocationsKind. + LLVM_PREFERRED_TYPE(SelectorLocationsKind) uint64_t SelLocsKind : 2; /// Whether this method overrides any other in the class hierarchy. @@ -1700,14 +1900,16 @@ class DeclContext { /// the same selector and is of the same kind (class or instance). /// A method in an implementation is not considered as overriding the same /// method in the interface or its categories. + LLVM_PREFERRED_TYPE(bool) uint64_t IsOverriding : 1; /// Indicates if the method was a definition but its body was skipped. + LLVM_PREFERRED_TYPE(bool) uint64_t HasSkippedBody : 1; }; - /// Number of non-inherited bits in ObjCMethodDeclBitfields. - enum { NumObjCMethodDeclBits = 24 }; + /// Number of inherited and non-inherited bits in ObjCMethodDeclBitfields. + enum { NumObjCMethodDeclBits = NumDeclContextBits + 24 }; /// Stores the bits used by ObjCContainerDecl. /// If modified NumObjCContainerDeclBits and the accessor @@ -1715,6 +1917,7 @@ class DeclContext { class ObjCContainerDeclBitfields { friend class ObjCContainerDecl; /// For the bits in DeclContextBitfields + LLVM_PREFERRED_TYPE(DeclContextBitfields) uint32_t : NumDeclContextBits; // Not a bitfield but this saves space. @@ -1722,10 +1925,10 @@ class DeclContext { SourceLocation AtStart; }; - /// Number of non-inherited bits in ObjCContainerDeclBitfields. + /// Number of inherited and non-inherited bits in ObjCContainerDeclBitfields. /// Note that here we rely on the fact that SourceLocation is 32 bits /// wide. We check this with the static_assert in the ctor of DeclContext. - enum { NumObjCContainerDeclBits = 64 - NumDeclContextBits }; + enum { NumObjCContainerDeclBits = 64 }; /// Stores the bits used by LinkageSpecDecl. /// If modified NumLinkageSpecDeclBits and the accessor @@ -1733,21 +1936,23 @@ class DeclContext { class LinkageSpecDeclBitfields { friend class LinkageSpecDecl; /// For the bits in DeclContextBitfields. + LLVM_PREFERRED_TYPE(DeclContextBitfields) uint64_t : NumDeclContextBits; - /// The language for this linkage specification with values - /// in the enum LinkageSpecDecl::LanguageIDs. + /// The language for this linkage specification. + LLVM_PREFERRED_TYPE(LinkageSpecLanguageIDs) uint64_t Language : 3; /// True if this linkage spec has braces. /// This is needed so that hasBraces() returns the correct result while the /// linkage spec body is being parsed. Once RBraceLoc has been set this is /// not used, so it doesn't need to be serialized. + LLVM_PREFERRED_TYPE(bool) uint64_t HasBraces : 1; }; - /// Number of non-inherited bits in LinkageSpecDeclBitfields. - enum { NumLinkageSpecDeclBits = 4 }; + /// Number of inherited and non-inherited bits in LinkageSpecDeclBitfields. + enum { NumLinkageSpecDeclBits = NumDeclContextBits + 4 }; /// Stores the bits used by BlockDecl. /// If modified NumBlockDeclBits and the accessor @@ -1755,25 +1960,32 @@ class DeclContext { class BlockDeclBitfields { friend class BlockDecl; /// For the bits in DeclContextBitfields. + LLVM_PREFERRED_TYPE(DeclContextBitfields) uint64_t : NumDeclContextBits; + LLVM_PREFERRED_TYPE(bool) uint64_t IsVariadic : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t CapturesCXXThis : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t BlockMissingReturnType : 1; + LLVM_PREFERRED_TYPE(bool) uint64_t IsConversionFromLambda : 1; /// A bit that indicates this block is passed directly to a function as a /// non-escaping parameter. + LLVM_PREFERRED_TYPE(bool) uint64_t DoesNotEscape : 1; /// A bit that indicates whether it's possible to avoid coying this block to /// the heap when it initializes or is assigned to a local variable with /// automatic storage. + LLVM_PREFERRED_TYPE(bool) uint64_t CanAvoidCopyToHeap : 1; }; - /// Number of non-inherited bits in BlockDeclBitfields. - enum { NumBlockDeclBits = 5 }; + /// Number of inherited and non-inherited bits in BlockDeclBitfields. + enum { NumBlockDeclBits = NumDeclContextBits + 5 }; /// Pointer to the data structure used to lookup declarations /// within this context (or a DependentStoredDeclsMap if this is a @@ -1850,6 +2062,10 @@ protected: public: ~DeclContext(); + // For use when debugging; hasValidDeclKind() will always return true for + // a correctly constructed object within its lifetime. + bool hasValidDeclKind() const; + Decl::Kind getDeclKind() const { return static_cast<Decl::Kind>(DeclContextBits.DeclKind); } @@ -1965,7 +2181,7 @@ public: /// Here, E is a transparent context, so its enumerator (Val1) will /// appear (semantically) that it is in the same context of E. /// Examples of transparent contexts include: enumerations (except for - /// C++0x scoped enums), and C++ linkage specifications. + /// C++0x scoped enums), C++ linkage specifications and export declaration. bool isTransparentContext() const; /// Determines whether this context or some of its ancestors is a @@ -1997,6 +2213,12 @@ public: return const_cast<DeclContext*>(this)->getNonClosureAncestor(); } + // Retrieve the nearest context that is not a transparent context. + DeclContext *getNonTransparentContext(); + const DeclContext *getNonTransparentContext() const { + return const_cast<DeclContext *>(this)->getNonTransparentContext(); + } + /// getPrimaryContext - There may be many different /// declarations of the same entity (including forward declarations /// of classes, multiple definitions of namespaces, etc.), each with @@ -2452,10 +2674,8 @@ public: D == LastDecl); } - bool setUseQualifiedLookup(bool use = true) const { - bool old_value = DeclContextBits.UseQualifiedLookup; + void setUseQualifiedLookup(bool use = true) const { DeclContextBits.UseQualifiedLookup = use; - return old_value; } bool shouldUseQualifiedLookup() const { @@ -2465,6 +2685,8 @@ public: static bool classof(const Decl *D); static bool classof(const DeclContext *D) { return true; } + void dumpAsDecl() const; + void dumpAsDecl(const ASTContext *Ctx) const; void dumpDeclContext() const; void dumpLookups() const; void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false, @@ -2514,14 +2736,6 @@ private: void reconcileExternalVisibleStorage() const; bool LoadLexicalDeclsFromExternalStorage() const; - /// Makes a declaration visible within this context, but - /// suppresses searches for external declarations with the same - /// name. - /// - /// Analogous to makeDeclVisibleInContext, but for the exclusive - /// use of addDeclInternal(). - void makeDeclVisibleInContextInternal(NamedDecl *D); - StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; void loadLazyLocalLexicalLookups(); diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h b/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h index 0d5ad40fc19e..9cebaff63bb0 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h @@ -64,7 +64,6 @@ class CXXFinalOverriderMap; class CXXIndirectPrimaryBaseSet; class CXXMethodDecl; class DecompositionDecl; -class DiagnosticBuilder; class FriendDecl; class FunctionTemplateDecl; class IdentifierInfo; @@ -155,22 +154,26 @@ class CXXBaseSpecifier { SourceLocation EllipsisLoc; /// Whether this is a virtual base class or not. + LLVM_PREFERRED_TYPE(bool) unsigned Virtual : 1; /// Whether this is the base of a class (true) or of a struct (false). /// /// This determines the mapping from the access specifier as written in the /// source code to the access specifier used for semantic analysis. + LLVM_PREFERRED_TYPE(bool) unsigned BaseOfClass : 1; /// Access specifier as written in the source code (may be AS_none). /// /// The actual type of data stored here is an AccessSpecifier, but we use - /// "unsigned" here to work around a VC++ bug. + /// "unsigned" here to work around Microsoft ABI. + LLVM_PREFERRED_TYPE(AccessSpecifier) unsigned Access : 2; /// Whether the class contains a using declaration /// to inherit the named class's constructors. + LLVM_PREFERRED_TYPE(bool) unsigned InheritConstructors : 1; /// The type of the base class. @@ -261,8 +264,9 @@ class CXXRecordDecl : public RecordDecl { friend class ASTWriter; friend class DeclContext; friend class LambdaExpr; + friend class ODRDiagsEmitter; - friend void FunctionDecl::setPure(bool); + friend void FunctionDecl::setIsPureVirtual(bool); friend void TagDecl::startDefinition(); /// Values used in DefinitionData fields to represent special members. @@ -276,21 +280,33 @@ class CXXRecordDecl : public RecordDecl { SMF_All = 0x3f }; +public: + enum LambdaDependencyKind { + LDK_Unknown = 0, + LDK_AlwaysDependent, + LDK_NeverDependent, + }; + +private: struct DefinitionData { #define FIELD(Name, Width, Merge) \ unsigned Name : Width; #include "CXXRecordDeclDefinitionBits.def" /// Whether this class describes a C++ lambda. + LLVM_PREFERRED_TYPE(bool) unsigned IsLambda : 1; /// Whether we are currently parsing base specifiers. + LLVM_PREFERRED_TYPE(bool) unsigned IsParsingBaseSpecifiers : 1; /// True when visible conversion functions are already computed /// and are available. + LLVM_PREFERRED_TYPE(bool) unsigned ComputedVisibleConversions : 1; + LLVM_PREFERRED_TYPE(bool) unsigned HasODRHash : 1; /// A hash of parts of the class to help in ODR checking. @@ -349,11 +365,11 @@ class CXXRecordDecl : public RecordDecl { } ArrayRef<CXXBaseSpecifier> bases() const { - return llvm::makeArrayRef(getBases(), NumBases); + return llvm::ArrayRef(getBases(), NumBases); } ArrayRef<CXXBaseSpecifier> vbases() const { - return llvm::makeArrayRef(getVBases(), NumVBases); + return llvm::ArrayRef(getVBases(), NumVBases); } private: @@ -375,46 +391,56 @@ class CXXRecordDecl : public RecordDecl { /// lambda will have been created with the enclosing context as its /// declaration context, rather than function. This is an unfortunate /// artifact of having to parse the default arguments before. - unsigned Dependent : 1; + LLVM_PREFERRED_TYPE(LambdaDependencyKind) + unsigned DependencyKind : 2; /// Whether this lambda is a generic lambda. + LLVM_PREFERRED_TYPE(bool) unsigned IsGenericLambda : 1; /// The Default Capture. + LLVM_PREFERRED_TYPE(LambdaCaptureDefault) unsigned CaptureDefault : 2; /// The number of captures in this lambda is limited 2^NumCaptures. unsigned NumCaptures : 15; /// The number of explicit captures in this lambda. - unsigned NumExplicitCaptures : 13; + unsigned NumExplicitCaptures : 12; /// Has known `internal` linkage. + LLVM_PREFERRED_TYPE(bool) unsigned HasKnownInternalLinkage : 1; /// The number used to indicate this lambda expression for name /// mangling in the Itanium C++ ABI. unsigned ManglingNumber : 31; + /// The index of this lambda within its context declaration. This is not in + /// general the same as the mangling number. + unsigned IndexInContext; + /// The declaration that provides context for this lambda, if the /// actual DeclContext does not suffice. This is used for lambdas that /// occur within default arguments of function parameters within the class /// or within a data member initializer. LazyDeclPtr ContextDecl; - /// The list of captures, both explicit and implicit, for this - /// lambda. - Capture *Captures = nullptr; + /// The lists of captures, both explicit and implicit, for this + /// lambda. One list is provided for each merged copy of the lambda. + /// The first list corresponds to the canonical definition. + /// The destructor is registered by AddCaptureList when necessary. + llvm::TinyPtrVector<Capture*> Captures; /// The type of the call method. TypeSourceInfo *MethodTyInfo; - LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent, + LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, unsigned DK, bool IsGeneric, LambdaCaptureDefault CaptureDefault) - : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric), + : DefinitionData(D), DependencyKind(DK), IsGenericLambda(IsGeneric), CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0), HasKnownInternalLinkage(0), ManglingNumber(0), - MethodTyInfo(Info) { + IndexInContext(0), MethodTyInfo(Info) { IsLambda = true; // C++1z [expr.prim.lambda]p4: @@ -422,6 +448,9 @@ class CXXRecordDecl : public RecordDecl { Aggregate = false; PlainOldData = false; } + + // Add a list of captures. + void AddCaptureList(ASTContext &Ctx, Capture *CaptureList); }; struct DefinitionData *dataPtr() const { @@ -548,7 +577,7 @@ public: bool DelayTypeCreation = false); static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, - bool DependentLambda, bool IsGeneric, + unsigned DependencyKind, bool IsGeneric, LambdaCaptureDefault CaptureDefault); static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); @@ -1035,6 +1064,12 @@ public: return static_cast<LambdaCaptureDefault>(getLambdaData().CaptureDefault); } + bool isCapturelessLambda() const { + if (!isLambda()) + return false; + return getLambdaCaptureDefault() == LCD_None && capture_size() == 0; + } + /// Set the captures for this lambda closure type. void setCaptures(ASTContext &Context, ArrayRef<LambdaCapture> Captures); @@ -1050,8 +1085,14 @@ public: /// /// \note No entries will be added for init-captures, as they do not capture /// variables. - void getCaptureFields(llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures, - FieldDecl *&ThisCapture) const; + /// + /// \note If multiple versions of the lambda are merged together, they may + /// have different variable declarations corresponding to the same capture. + /// In that case, all of those variable declarations will be added to the + /// Captures list, so it may have more than one variable listed per field. + void + getCaptureFields(llvm::DenseMap<const ValueDecl *, FieldDecl *> &Captures, + FieldDecl *&ThisCapture) const; using capture_const_iterator = const LambdaCapture *; using capture_const_range = llvm::iterator_range<capture_const_iterator>; @@ -1061,7 +1102,9 @@ public: } capture_const_iterator captures_begin() const { - return isLambda() ? getLambdaData().Captures : nullptr; + if (!isLambda()) return nullptr; + LambdaDefinitionData &LambdaData = getLambdaData(); + return LambdaData.Captures.empty() ? nullptr : LambdaData.Captures.front(); } capture_const_iterator captures_end() const { @@ -1071,6 +1114,11 @@ public: unsigned capture_size() const { return getLambdaData().NumCaptures; } + const LambdaCapture *getCapture(unsigned I) const { + assert(isLambda() && I < capture_size() && "invalid index for capture"); + return captures_begin() + I; + } + using conversion_iterator = UnresolvedSetIterator; conversion_iterator conversion_begin() const { @@ -1139,6 +1187,13 @@ public: /// /// \note This does NOT include a check for union-ness. bool isEmpty() const { return data().Empty; } + /// Marks this record as empty. This is used by DWARFASTParserClang + /// when parsing records with empty fields having [[no_unique_address]] + /// attribute + void markEmpty() { data().Empty = true; } + + void setInitMethod(bool Val) { data().HasInitMethod = Val; } + bool hasInitMethod() const { return data().HasInitMethod; } bool hasPrivateFields() const { return data().HasPrivateFields; @@ -1160,7 +1215,7 @@ public: /// Determine whether this class has a pure virtual function. /// - /// The class is is abstract per (C++ [class.abstract]p2) if it declares + /// The class is abstract per (C++ [class.abstract]p2) if it declares /// a pure virtual function or inherits a pure virtual function that is /// not overridden. bool isAbstract() const { return data().Abstract; } @@ -1370,6 +1425,9 @@ public: /// (C++11 [class]p6). bool isTriviallyCopyable() const; + /// Determine whether this class is considered trivially copyable per + bool isTriviallyCopyConstructible() const; + /// Determine whether this class is considered trivial. /// /// C++11 [class]p6: @@ -1381,37 +1439,39 @@ public: /// Determine whether this class is a literal type. /// - /// C++11 [basic.types]p10: + /// C++20 [basic.types]p10: /// A class type that has all the following properties: - /// - it has a trivial destructor - /// - every constructor call and full-expression in the - /// brace-or-equal-intializers for non-static data members (if any) is - /// a constant expression. - /// - it is an aggregate type or has at least one constexpr constructor - /// or constructor template that is not a copy or move constructor, and - /// - all of its non-static data members and base classes are of literal - /// types - /// - /// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by - /// treating types with trivial default constructors as literal types. - /// - /// Only in C++17 and beyond, are lambdas literal types. - bool isLiteral() const { - const LangOptions &LangOpts = getLangOpts(); - return (LangOpts.CPlusPlus20 ? hasConstexprDestructor() - : hasTrivialDestructor()) && - (!isLambda() || LangOpts.CPlusPlus17) && - !hasNonLiteralTypeFieldsOrBases() && - (isAggregate() || isLambda() || - hasConstexprNonCopyMoveConstructor() || - hasTrivialDefaultConstructor()); - } + /// - it has a constexpr destructor + /// - all of its non-static non-variant data members and base classes + /// are of non-volatile literal types, and it: + /// - is a closure type + /// - is an aggregate union type that has either no variant members + /// or at least one variant member of non-volatile literal type + /// - is a non-union aggregate type for which each of its anonymous + /// union members satisfies the above requirements for an aggregate + /// union type, or + /// - has at least one constexpr constructor or constructor template + /// that is not a copy or move constructor. + bool isLiteral() const; /// Determine whether this is a structural type. bool isStructural() const { return isLiteral() && data().StructuralIfLiteral; } + /// Notify the class that this destructor is now selected. + /// + /// Important properties of the class depend on destructor properties. Since + /// C++20, it is possible to have multiple destructor declarations in a class + /// out of which one will be selected at the end. + /// This is called separately from addedMember because it has to be deferred + /// to the completion of the class. + void addedSelectedDestructor(CXXDestructorDecl *DD); + + /// Notify the class that an eligible SMF has been added. + /// This updates triviality and destructor based properties of the class accordingly. + void addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD, unsigned SMKind); + /// If this record is an instantiation of a member class, /// retrieves the member class from which it was instantiated. /// @@ -1726,18 +1786,31 @@ public: /// the declaration context suffices. Decl *getLambdaContextDecl() const; - /// Set the mangling number and context declaration for a lambda - /// class. - void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl, - bool HasKnownInternalLinkage = false) { + /// Retrieve the index of this lambda within the context declaration returned + /// by getLambdaContextDecl(). + unsigned getLambdaIndexInContext() const { assert(isLambda() && "Not a lambda closure type!"); - getLambdaData().ManglingNumber = ManglingNumber; - getLambdaData().ContextDecl = ContextDecl; - getLambdaData().HasKnownInternalLinkage = HasKnownInternalLinkage; + return getLambdaData().IndexInContext; } - /// Set the device side mangling number. - void setDeviceLambdaManglingNumber(unsigned Num) const; + /// Information about how a lambda is numbered within its context. + struct LambdaNumbering { + Decl *ContextDecl = nullptr; + unsigned IndexInContext = 0; + unsigned ManglingNumber = 0; + unsigned DeviceManglingNumber = 0; + bool HasKnownInternalLinkage = false; + }; + + /// Set the mangling numbers and context declaration for a lambda class. + void setLambdaNumbering(LambdaNumbering Numbering); + + // Get the mangling numbers and context declaration for a lambda class. + LambdaNumbering getLambdaNumbering() const { + return {getLambdaContextDecl(), getLambdaIndexInContext(), + getLambdaManglingNumber(), getDeviceLambdaManglingNumber(), + hasKnownLambdaInternalLinkage()}; + } /// Retrieve the device side mangling number. unsigned getDeviceLambdaManglingNumber() const; @@ -1772,13 +1845,37 @@ public: /// function declaration itself is dependent. This flag indicates when we /// know that the lambda is dependent despite that. bool isDependentLambda() const { - return isLambda() && getLambdaData().Dependent; + return isLambda() && getLambdaData().DependencyKind == LDK_AlwaysDependent; + } + + bool isNeverDependentLambda() const { + return isLambda() && getLambdaData().DependencyKind == LDK_NeverDependent; + } + + unsigned getLambdaDependencyKind() const { + if (!isLambda()) + return LDK_Unknown; + return getLambdaData().DependencyKind; } TypeSourceInfo *getLambdaTypeInfo() const { return getLambdaData().MethodTyInfo; } + void setLambdaTypeInfo(TypeSourceInfo *TS) { + assert(DefinitionData && DefinitionData->IsLambda && + "setting lambda property of non-lambda class"); + auto &DL = static_cast<LambdaDefinitionData &>(*DefinitionData); + DL.MethodTyInfo = TS; + } + + void setLambdaIsGeneric(bool IsGeneric) { + assert(DefinitionData && DefinitionData->IsLambda && + "setting lambda property of non-lambda class"); + auto &DL = static_cast<LambdaDefinitionData &>(*DefinitionData); + DL.IsGenericLambda = IsGeneric; + } + // Determine whether this type is an Interface Like type for // __interface inheritance purposes. bool isInterfaceLike() const; @@ -1855,13 +1952,13 @@ private: ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, SourceLocation EndLocation, - CXXConstructorDecl *Ctor) + CXXConstructorDecl *Ctor, DeductionCandidate Kind) : FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo, - SC_None, false, ConstexprSpecKind::Unspecified), + SC_None, false, false, ConstexprSpecKind::Unspecified), Ctor(Ctor), ExplicitSpec(ES) { if (EndLocation.isValid()) setRangeEnd(EndLocation); - setIsCopyDeductionCandidate(false); + setDeductionCandidateKind(Kind); } CXXConstructorDecl *Ctor; @@ -1876,14 +1973,15 @@ public: Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, SourceLocation EndLocation, - CXXConstructorDecl *Ctor = nullptr); + CXXConstructorDecl *Ctor = nullptr, + DeductionCandidate Kind = DeductionCandidate::Normal); static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, unsigned ID); ExplicitSpecifier getExplicitSpecifier() { return ExplicitSpec; } const ExplicitSpecifier getExplicitSpecifier() const { return ExplicitSpec; } - /// Return true if the declartion is already resolved to be explicit. + /// Return true if the declaration is already resolved to be explicit. bool isExplicit() const { return ExplicitSpec.isExplicit(); } /// Get the template for which this guide performs deduction. @@ -1893,16 +1991,15 @@ public: /// Get the constructor from which this deduction guide was generated, if /// this is an implicit deduction guide. - CXXConstructorDecl *getCorrespondingConstructor() const { - return Ctor; - } + CXXConstructorDecl *getCorrespondingConstructor() const { return Ctor; } - void setIsCopyDeductionCandidate(bool isCDC = true) { - FunctionDeclBits.IsCopyDeductionCandidate = isCDC; + void setDeductionCandidateKind(DeductionCandidate K) { + FunctionDeclBits.DeductionCandidateKind = static_cast<unsigned char>(K); } - bool isCopyDeductionCandidate() const { - return FunctionDeclBits.IsCopyDeductionCandidate; + DeductionCandidate getDeductionCandidateKind() const { + return static_cast<DeductionCandidate>( + FunctionDeclBits.DeductionCandidateKind); } // Implement isa/cast/dyncast/etc. @@ -1939,6 +2036,14 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == RequiresExprBody; } + + static DeclContext *castToDeclContext(const RequiresExprBodyDecl *D) { + return static_cast<DeclContext *>(const_cast<RequiresExprBodyDecl *>(D)); + } + + static RequiresExprBodyDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<RequiresExprBodyDecl *>(const_cast<DeclContext *>(DC)); + } }; /// Represents a static or instance method of a struct/union/class. @@ -1952,29 +2057,39 @@ protected: CXXMethodDecl(Kind DK, ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, - bool isInline, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, + bool UsesFPIntrin, bool isInline, + ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr) - : FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, SC, isInline, - ConstexprKind, TrailingRequiresClause) { + : FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin, + isInline, ConstexprKind, TrailingRequiresClause) { if (EndLocation.isValid()) setRangeEnd(EndLocation); } public: - static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, StorageClass SC, - bool isInline, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, - Expr *TrailingRequiresClause = nullptr); + static CXXMethodDecl * + Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + StorageClass SC, bool UsesFPIntrin, bool isInline, + ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, + Expr *TrailingRequiresClause = nullptr); static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); bool isStatic() const; bool isInstance() const { return !isStatic(); } + /// [C++2b][dcl.fct]/p7 + /// An explicit object member function is a non-static + /// member function with an explicit object parameter. e.g., + /// void func(this SomeType); + bool isExplicitObjectMemberFunction() const; + + /// [C++2b][dcl.fct]/p7 + /// An implicit object member function is a non-static + /// member function without an explicit object parameter. + bool isImplicitObjectMemberFunction() const; + /// Returns true if the given operator is implicitly static in a record /// context. static bool isStaticOverloadedOperator(OverloadedOperatorKind OOK) { @@ -1995,7 +2110,7 @@ public: // Member function is virtual if it is marked explicitly so, or if it is // declared in __interface -- then it is automatically pure virtual. - if (CD->isVirtualAsWritten() || CD->isPure()) + if (CD->isVirtualAsWritten() || CD->isPureVirtual()) return true; return CD->size_overridden_methods() != 0; @@ -2083,14 +2198,19 @@ public: /// Return the type of the object pointed by \c this. /// /// See getThisType() for usage restriction. - QualType getThisObjectType() const; + + QualType getFunctionObjectParameterReferenceType() const; + QualType getFunctionObjectParameterType() const { + return getFunctionObjectParameterReferenceType().getNonReferenceType(); + } + + unsigned getNumExplicitParams() const { + return getNumParams() - (isExplicitObjectMemberFunction() ? 1 : 0); + } static QualType getThisType(const FunctionProtoType *FPT, const CXXRecordDecl *Decl); - static QualType getThisObjectType(const FunctionProtoType *FPT, - const CXXRecordDecl *Decl); - Qualifiers getMethodQualifiers() const { return getType()->castAs<FunctionProtoType>()->getMethodQuals(); } @@ -2197,14 +2317,17 @@ class CXXCtorInitializer final { /// If the initializee is a type, whether that type makes this /// a delegating initialization. + LLVM_PREFERRED_TYPE(bool) unsigned IsDelegating : 1; /// If the initializer is a base initializer, this keeps track /// of whether the base is virtual or not. + LLVM_PREFERRED_TYPE(bool) unsigned IsVirtual : 1; /// Whether or not the initializer is explicitly written /// in the sources. + LLVM_PREFERRED_TYPE(bool) unsigned IsWritten : 1; /// If IsWritten is true, then this number keeps track of the textual order @@ -2413,7 +2536,8 @@ class CXXConstructorDecl final CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool isInline, + TypeSourceInfo *TInfo, ExplicitSpecifier ES, + bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited, Expr *TrailingRequiresClause); @@ -2456,8 +2580,8 @@ public: static CXXConstructorDecl * Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind, + ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline, + bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited = InheritedConstructor(), Expr *TrailingRequiresClause = nullptr); @@ -2479,7 +2603,7 @@ public: return getCanonicalDecl()->getExplicitSpecifierInternal(); } - /// Return true if the declartion is already resolved to be explicit. + /// Return true if the declaration is already resolved to be explicit. bool isExplicit() const { return getExplicitSpecifier().isExplicit(); } /// Iterates through the member/base initializer list. @@ -2676,25 +2800,24 @@ class CXXDestructorDecl : public CXXMethodDecl { CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, bool isInline, + TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause = nullptr) : CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, ConstexprKind, SourceLocation(), - TrailingRequiresClause) { + SC_None, UsesFPIntrin, isInline, ConstexprKind, + SourceLocation(), TrailingRequiresClause) { setImplicit(isImplicitlyDeclared); } void anchor() override; public: - static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause = nullptr); + static CXXDestructorDecl * + Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, + ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause = nullptr); static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID); void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg); @@ -2732,12 +2855,13 @@ public: class CXXConversionDecl : public CXXMethodDecl { CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, bool isInline, ExplicitSpecifier ES, - ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, + TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline, + ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, + SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr) : CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, ConstexprKind, EndLocation, - TrailingRequiresClause), + SC_None, UsesFPIntrin, isInline, ConstexprKind, + EndLocation, TrailingRequiresClause), ExplicitSpec(ES) {} void anchor() override; @@ -2750,8 +2874,9 @@ public: static CXXConversionDecl * Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr); + bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES, + ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, + Expr *TrailingRequiresClause = nullptr); static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID); ExplicitSpecifier getExplicitSpecifier() { @@ -2762,7 +2887,7 @@ public: return getCanonicalDecl()->ExplicitSpec; } - /// Return true if the declartion is already resolved to be explicit. + /// Return true if the declaration is already resolved to be explicit. bool isExplicit() const { return getExplicitSpecifier().isExplicit(); } void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; } @@ -2787,6 +2912,12 @@ public: static bool classofKind(Kind K) { return K == CXXConversion; } }; +/// Represents the language in a linkage specification. +/// +/// The values are part of the serialization ABI for +/// ASTs and cannot be changed without altering that ABI. +enum class LinkageSpecLanguageIDs { C = 1, CXX = 2 }; + /// Represents a linkage specification. /// /// For example: @@ -2797,14 +2928,7 @@ class LinkageSpecDecl : public Decl, public DeclContext { virtual void anchor(); // This class stores some data in DeclContext::LinkageSpecDeclBits to save // some space. Use the provided accessors to access it. -public: - /// Represents the language in a linkage specification. - /// - /// The values are part of the serialization ABI for - /// ASTs and cannot be changed without altering that ABI. - enum LanguageIDs { lang_c = 1, lang_cxx = 2 }; -private: /// The source location for the extern keyword. SourceLocation ExternLoc; @@ -2812,22 +2936,25 @@ private: SourceLocation RBraceLoc; LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc, - SourceLocation LangLoc, LanguageIDs lang, bool HasBraces); + SourceLocation LangLoc, LinkageSpecLanguageIDs lang, + bool HasBraces); public: static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation ExternLoc, - SourceLocation LangLoc, LanguageIDs Lang, - bool HasBraces); + SourceLocation LangLoc, + LinkageSpecLanguageIDs Lang, bool HasBraces); static LinkageSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID); /// Return the language specified by this linkage specification. - LanguageIDs getLanguage() const { - return static_cast<LanguageIDs>(LinkageSpecDeclBits.Language); + LinkageSpecLanguageIDs getLanguage() const { + return static_cast<LinkageSpecLanguageIDs>(LinkageSpecDeclBits.Language); } /// Set the language specified by this linkage specification. - void setLanguage(LanguageIDs L) { LinkageSpecDeclBits.Language = L; } + void setLanguage(LinkageSpecLanguageIDs L) { + LinkageSpecDeclBits.Language = llvm::to_underlying(L); + } /// Determines whether this linkage specification had braces in /// its syntactic form. @@ -3290,7 +3417,7 @@ class BaseUsingDecl : public NamedDecl { protected: BaseUsingDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) - : NamedDecl(DK, DC, L, N), FirstUsingShadow(nullptr, 0) {} + : NamedDecl(DK, DC, L, N), FirstUsingShadow(nullptr, false) {} private: void anchor() override; @@ -3476,6 +3603,7 @@ class ConstructorUsingShadowDecl final : public UsingShadowDecl { /// \c true if the constructor ultimately named by this using shadow /// declaration is within a virtual base class subobject of the class that /// contains this declaration. + LLVM_PREFERRED_TYPE(bool) unsigned IsVirtual : 1; ConstructorUsingShadowDecl(ASTContext &C, DeclContext *DC, SourceLocation Loc, @@ -3578,17 +3706,15 @@ public: class UsingEnumDecl : public BaseUsingDecl, public Mergeable<UsingEnumDecl> { /// The source location of the 'using' keyword itself. SourceLocation UsingLocation; - - /// Location of the 'enum' keyword. + /// The source location of the 'enum' keyword. SourceLocation EnumLocation; - - /// The enum - EnumDecl *Enum; + /// 'qual::SomeEnum' as an EnumType, possibly with Elaborated/Typedef sugar. + TypeSourceInfo *EnumType; UsingEnumDecl(DeclContext *DC, DeclarationName DN, SourceLocation UL, - SourceLocation EL, SourceLocation NL, EnumDecl *ED) - : BaseUsingDecl(UsingEnum, DC, NL, DN), UsingLocation(UL), - EnumLocation(EL), Enum(ED) {} + SourceLocation EL, SourceLocation NL, TypeSourceInfo *EnumType) + : BaseUsingDecl(UsingEnum, DC, NL, DN), UsingLocation(UL), EnumLocation(EL), + EnumType(EnumType){} void anchor() override; @@ -3603,13 +3729,29 @@ public: /// The source location of the 'enum' keyword. SourceLocation getEnumLoc() const { return EnumLocation; } void setEnumLoc(SourceLocation L) { EnumLocation = L; } + NestedNameSpecifier *getQualifier() const { + return getQualifierLoc().getNestedNameSpecifier(); + } + NestedNameSpecifierLoc getQualifierLoc() const { + if (auto ETL = EnumType->getTypeLoc().getAs<ElaboratedTypeLoc>()) + return ETL.getQualifierLoc(); + return NestedNameSpecifierLoc(); + } + // Returns the "qualifier::Name" part as a TypeLoc. + TypeLoc getEnumTypeLoc() const { + return EnumType->getTypeLoc(); + } + TypeSourceInfo *getEnumType() const { + return EnumType; + } + void setEnumType(TypeSourceInfo *TSI) { EnumType = TSI; } public: - EnumDecl *getEnumDecl() const { return Enum; } + EnumDecl *getEnumDecl() const { return cast<EnumDecl>(EnumType->getType()->getAsTagDecl()); } static UsingEnumDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation UsingL, SourceLocation EnumL, - SourceLocation NameL, EnumDecl *ED); + SourceLocation NameL, TypeSourceInfo *EnumType); static UsingEnumDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -3677,7 +3819,7 @@ public: /// Get the set of using declarations that this pack expanded into. Note that /// some of these may still be unresolved. ArrayRef<NamedDecl *> expansions() const { - return llvm::makeArrayRef(getTrailingObjects<NamedDecl *>(), NumExpansions); + return llvm::ArrayRef(getTrailingObjects<NamedDecl *>(), NumExpansions); } static UsingPackDecl *Create(ASTContext &C, DeclContext *DC, @@ -3908,12 +4050,12 @@ public: /// Represents a C++11 static_assert declaration. class StaticAssertDecl : public Decl { llvm::PointerIntPair<Expr *, 1, bool> AssertExprAndFailed; - StringLiteral *Message; + Expr *Message; SourceLocation RParenLoc; StaticAssertDecl(DeclContext *DC, SourceLocation StaticAssertLoc, - Expr *AssertExpr, StringLiteral *Message, - SourceLocation RParenLoc, bool Failed) + Expr *AssertExpr, Expr *Message, SourceLocation RParenLoc, + bool Failed) : Decl(StaticAssert, DC, StaticAssertLoc), AssertExprAndFailed(AssertExpr, Failed), Message(Message), RParenLoc(RParenLoc) {} @@ -3925,15 +4067,15 @@ public: static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StaticAssertLoc, - Expr *AssertExpr, StringLiteral *Message, + Expr *AssertExpr, Expr *Message, SourceLocation RParenLoc, bool Failed); static StaticAssertDecl *CreateDeserialized(ASTContext &C, unsigned ID); Expr *getAssertExpr() { return AssertExprAndFailed.getPointer(); } const Expr *getAssertExpr() const { return AssertExprAndFailed.getPointer(); } - StringLiteral *getMessage() { return Message; } - const StringLiteral *getMessage() const { return Message; } + Expr *getMessage() { return Message; } + const Expr *getMessage() const { return Message; } bool isFailed() const { return AssertExprAndFailed.getInt(); } @@ -4047,10 +4189,10 @@ public: unsigned NumBindings); ArrayRef<BindingDecl *> bindings() const { - return llvm::makeArrayRef(getTrailingObjects<BindingDecl *>(), NumBindings); + return llvm::ArrayRef(getTrailingObjects<BindingDecl *>(), NumBindings); } - void printName(raw_ostream &os) const override; + void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override; static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Decomposition; } @@ -4163,7 +4305,8 @@ private: public: /// Print this UUID in a human-readable format. - void printName(llvm::raw_ostream &OS) const override; + void printName(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const override; /// Get the decomposed parts of this declaration. Parts getParts() const { return PartVal; } @@ -4185,6 +4328,55 @@ public: static bool classofKind(Kind K) { return K == Decl::MSGuid; } }; +/// An artificial decl, representing a global anonymous constant value which is +/// uniquified by value within a translation unit. +/// +/// These is currently only used to back the LValue returned by +/// __builtin_source_location, but could potentially be used for other similar +/// situations in the future. +class UnnamedGlobalConstantDecl : public ValueDecl, + public Mergeable<UnnamedGlobalConstantDecl>, + public llvm::FoldingSetNode { + + // The constant value of this global. + APValue Value; + + void anchor() override; + + UnnamedGlobalConstantDecl(const ASTContext &C, DeclContext *DC, QualType T, + const APValue &Val); + + static UnnamedGlobalConstantDecl *Create(const ASTContext &C, QualType T, + const APValue &APVal); + static UnnamedGlobalConstantDecl *CreateDeserialized(ASTContext &C, + unsigned ID); + + // Only ASTContext::getUnnamedGlobalConstantDecl and deserialization create + // these. + friend class ASTContext; + friend class ASTReader; + friend class ASTDeclReader; + +public: + /// Print this in a human-readable format. + void printName(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const override; + + const APValue &getValue() const { return Value; } + + static void Profile(llvm::FoldingSetNodeID &ID, QualType Ty, + const APValue &APVal) { + Ty.Profile(ID); + APVal.Profile(ID); + } + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getType(), getValue()); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Decl::UnnamedGlobalConstant; } +}; + /// Insertion operator for diagnostics. This allows sending an AccessSpecifier /// into a diagnostic with <<. const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclContextInternals.h b/contrib/llvm-project/clang/include/clang/AST/DeclContextInternals.h index 2eef2343b750..903cdb7bfcc8 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclContextInternals.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclContextInternals.h @@ -78,8 +78,7 @@ class StoredDeclsList { } Data.setPointer(NewHead); - assert(llvm::find_if(getLookupResult(), ShouldErase) == - getLookupResult().end() && "Still exists!"); + assert(llvm::none_of(getLookupResult(), ShouldErase) && "Still exists!"); } void erase(NamedDecl *ND) { @@ -91,7 +90,7 @@ public: StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) { RHS.Data.setPointer(nullptr); - RHS.Data.setInt(0); + RHS.Data.setInt(false); } void MaybeDeallocList() { @@ -115,7 +114,7 @@ public: Data = RHS.Data; RHS.Data.setPointer(nullptr); - RHS.Data.setInt(0); + RHS.Data.setInt(false); return *this; } @@ -143,7 +142,7 @@ public: } void setHasExternalDecls() { - Data.setInt(1); + Data.setInt(true); } void remove(NamedDecl *D) { @@ -156,7 +155,7 @@ public: erase_if([](NamedDecl *ND) { return ND->isFromASTFile(); }); // Don't have any pending external decls any more. - Data.setInt(0); + Data.setInt(false); } void replaceExternalDecls(ArrayRef<NamedDecl*> Decls) { @@ -172,7 +171,7 @@ public: }); // Don't have any pending external decls any more. - Data.setInt(0); + Data.setInt(false); if (Decls.empty()) return; diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclFriend.h b/contrib/llvm-project/clang/include/clang/AST/DeclFriend.h index 6f8306c6025e..3e6ca5b32192 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclFriend.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclFriend.h @@ -23,7 +23,6 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/None.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" @@ -74,6 +73,7 @@ private: /// True if this 'friend' declaration is unsupported. Eventually we /// will support every possible friend declaration, but for now we /// silently ignore some and set this flag to authorize all access. + LLVM_PREFERRED_TYPE(bool) unsigned UnsupportedFriend : 1; // The number of "outer" template parameter lists in non-templatic @@ -108,11 +108,10 @@ public: friend class ASTNodeImporter; friend TrailingObjects; - static FriendDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, FriendUnion Friend_, - SourceLocation FriendL, - ArrayRef<TemplateParameterList*> FriendTypeTPLists - = None); + static FriendDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_, + SourceLocation FriendL, + ArrayRef<TemplateParameterList *> FriendTypeTPLists = std::nullopt); static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID, unsigned FriendTypeNumTPLists); diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclObjC.h b/contrib/llvm-project/clang/include/clang/AST/DeclObjC.h index 6bb9cdf67034..f8f894b4b10d 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclObjC.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclObjC.h @@ -25,9 +25,8 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/None.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" @@ -116,6 +115,8 @@ public: const SourceLocation *Locs, ASTContext &Ctx); }; +enum class ObjCImplementationControl { None, Required, Optional }; + /// ObjCMethodDecl - Represents an instance or class method declaration. /// ObjC methods can be declared within 4 contexts: class interfaces, /// categories, protocols, and class implementations. While C++ member @@ -140,10 +141,6 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext { // This class stores some data in DeclContext::ObjCMethodDeclBits // to save some space. Use the provided accessors to access it. -public: - enum ImplementationControl { None, Required, Optional }; - -private: /// Return type of this method. QualType MethodDeclType; @@ -169,14 +166,14 @@ private: /// constructed by createImplicitParams. ImplicitParamDecl *CmdDecl = nullptr; - ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc, - Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, - DeclContext *contextDecl, bool isInstance = true, - bool isVariadic = false, bool isPropertyAccessor = false, - bool isSynthesizedAccessorStub = false, - bool isImplicitlyDeclared = false, bool isDefined = false, - ImplementationControl impControl = None, - bool HasRelatedResultType = false); + ObjCMethodDecl( + SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, + QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl, + bool isInstance = true, bool isVariadic = false, + bool isPropertyAccessor = false, bool isSynthesizedAccessorStub = false, + bool isImplicitlyDeclared = false, bool isDefined = false, + ObjCImplementationControl impControl = ObjCImplementationControl::None, + bool HasRelatedResultType = false); SelectorLocationsKind getSelLocsKind() const { return static_cast<SelectorLocationsKind>(ObjCMethodDeclBits.SelLocsKind); @@ -236,7 +233,7 @@ public: bool isVariadic = false, bool isPropertyAccessor = false, bool isSynthesizedAccessorStub = false, bool isImplicitlyDeclared = false, bool isDefined = false, - ImplementationControl impControl = None, + ObjCImplementationControl impControl = ObjCImplementationControl::None, bool HasRelatedResultType = false); static ObjCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -374,8 +371,7 @@ public: // ArrayRef access to formal parameters. This should eventually // replace the iterator interface above. ArrayRef<ParmVarDecl*> parameters() const { - return llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()), - NumParams); + return llvm::ArrayRef(const_cast<ParmVarDecl **>(getParams()), NumParams); } ParmVarDecl *getParamDecl(unsigned Idx) { @@ -389,9 +385,8 @@ public: /// Sets the method's parameters and selector source locations. /// If the method is implicit (not coming from source) \p SelLocs is /// ignored. - void setMethodParams(ASTContext &C, - ArrayRef<ParmVarDecl*> Params, - ArrayRef<SourceLocation> SelLocs = llvm::None); + void setMethodParams(ASTContext &C, ArrayRef<ParmVarDecl *> Params, + ArrayRef<SourceLocation> SelLocs = std::nullopt); // Iterator access to parameter types. struct GetTypeFn { @@ -487,6 +482,9 @@ public: /// True if the method is tagged as objc_direct bool isDirectMethod() const; + /// True if the method has a parameter that's destroyed in the callee. + bool hasParamDestroyedInCallee() const; + /// Returns the property associated with this method's selector. /// /// Note that even if this particular method is not marked as a property @@ -495,16 +493,17 @@ public: const ObjCPropertyDecl *findPropertyDecl(bool CheckOverrides = true) const; // Related to protocols declared in \@protocol - void setDeclImplementation(ImplementationControl ic) { - ObjCMethodDeclBits.DeclImplementation = ic; + void setDeclImplementation(ObjCImplementationControl ic) { + ObjCMethodDeclBits.DeclImplementation = llvm::to_underlying(ic); } - ImplementationControl getImplementationControl() const { - return ImplementationControl(ObjCMethodDeclBits.DeclImplementation); + ObjCImplementationControl getImplementationControl() const { + return static_cast<ObjCImplementationControl>( + ObjCMethodDeclBits.DeclImplementation); } bool isOptional() const { - return getImplementationControl() == Optional; + return getImplementationControl() == ObjCImplementationControl::Optional; } /// Returns true if this specific method declaration is marked with the @@ -581,6 +580,7 @@ class ObjCTypeParamDecl : public TypedefNameDecl { unsigned Index : 14; /// The variance of the type parameter. + LLVM_PREFERRED_TYPE(ObjCTypeParamVariance) unsigned Variance : 2; /// The location of the variance, if any. @@ -742,10 +742,13 @@ private: QualType DeclType; TypeSourceInfo *DeclTypeSourceInfo; + LLVM_PREFERRED_TYPE(ObjCPropertyAttribute::Kind) unsigned PropertyAttributes : NumObjCPropertyAttrsBits; + LLVM_PREFERRED_TYPE(ObjCPropertyAttribute::Kind) unsigned PropertyAttributesAsWritten : NumObjCPropertyAttrsBits; // \@required/\@optional + LLVM_PREFERRED_TYPE(PropertyControl) unsigned PropertyImplementation : 2; // getter name of NULL if no getter @@ -776,17 +779,13 @@ private: LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI), PropertyAttributes(ObjCPropertyAttribute::kind_noattr), PropertyAttributesAsWritten(ObjCPropertyAttribute::kind_noattr), - PropertyImplementation(propControl), GetterName(Selector()), - SetterName(Selector()) {} + PropertyImplementation(propControl) {} public: - static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - IdentifierInfo *Id, SourceLocation AtLocation, - SourceLocation LParenLocation, - QualType T, - TypeSourceInfo *TSI, - PropertyControl propControl = None); + static ObjCPropertyDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + SourceLocation AtLocation, SourceLocation LParenLocation, QualType T, + TypeSourceInfo *TSI, PropertyControl propControl = None); static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1072,21 +1071,23 @@ public: bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const; ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const; + ObjCPropertyDecl *getProperty(const IdentifierInfo *Id, + bool IsInstance) const; + ObjCPropertyDecl * FindPropertyDeclaration(const IdentifierInfo *PropertyId, ObjCPropertyQueryKind QueryKind) const; using PropertyMap = - llvm::DenseMap<std::pair<IdentifierInfo *, unsigned/*isClassProperty*/>, - ObjCPropertyDecl *>; + llvm::MapVector<std::pair<IdentifierInfo *, unsigned /*isClassProperty*/>, + ObjCPropertyDecl *>; using ProtocolPropertySet = llvm::SmallDenseSet<const ObjCProtocolDecl *, 8>; using PropertyDeclOrder = llvm::SmallVector<ObjCPropertyDecl *, 8>; /// This routine collects list of properties to be implemented in the class. /// This includes, class's and its conforming protocols' properties. /// Note, the superclass's properties are not included in the list. - virtual void collectPropertiesToImplement(PropertyMap &PM, - PropertyDeclOrder &PO) const {} + virtual void collectPropertiesToImplement(PropertyMap &PM) const {} SourceLocation getAtStartLoc() const { return ObjCContainerDeclBits.AtStart; } @@ -1148,6 +1149,7 @@ public: class ObjCInterfaceDecl : public ObjCContainerDecl , public Redeclarable<ObjCInterfaceDecl> { friend class ASTContext; + friend class ODRDiagsEmitter; /// TypeForDecl - This indicates the Type object that represents this /// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType @@ -1180,14 +1182,17 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// Indicates that the contents of this Objective-C class will be /// completed by the external AST source when required. + LLVM_PREFERRED_TYPE(bool) mutable unsigned ExternallyCompleted : 1; /// Indicates that the ivar cache does not yet include ivars /// declared in the implementation. + LLVM_PREFERRED_TYPE(bool) mutable unsigned IvarListMissingImplementation : 1; /// Indicates that this interface decl contains at least one initializer /// marked with the 'objc_designated_initializer' attribute. + LLVM_PREFERRED_TYPE(bool) unsigned HasDesignatedInitializers : 1; enum InheritedDesignatedInitializersState { @@ -1203,8 +1208,16 @@ class ObjCInterfaceDecl : public ObjCContainerDecl }; /// One of the \c InheritedDesignatedInitializersState enumeratos. + LLVM_PREFERRED_TYPE(InheritedDesignatedInitializersState) mutable unsigned InheritedDesignatedInitializers : 2; + /// Tracks whether a ODR hash has been computed for this interface. + LLVM_PREFERRED_TYPE(bool) + unsigned HasODRHash : 1; + + /// A hash of parts of the class to help in ODR checking. + unsigned ODRHash = 0; + /// The location of the last location in this declaration, before /// the properties/methods. For example, this will be the '>', '}', or /// identifier, @@ -1213,7 +1226,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl DefinitionData() : ExternallyCompleted(false), IvarListMissingImplementation(true), HasDesignatedInitializers(false), - InheritedDesignatedInitializers(IDI_Unknown) {} + InheritedDesignatedInitializers(IDI_Unknown), HasODRHash(false) {} }; /// The type parameters associated with this class, if any. @@ -1537,6 +1550,13 @@ public: /// a forward declaration (\@class) to a definition (\@interface). void startDefinition(); + /// Starts the definition without sharing it with other redeclarations. + /// Such definition shouldn't be used for anything but only to compare if + /// a duplicate is compatible with previous definition or if it is + /// a distinct duplicate. + void startDuplicateDefinitionForComparison(); + void mergeDuplicateDefinitionWithCommon(const ObjCInterfaceDecl *Definition); + /// Retrieve the superclass type. const ObjCObjectType *getSuperClassType() const { if (TypeSourceInfo *TInfo = getSuperClassTInfo()) @@ -1778,8 +1798,7 @@ public: *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId, ObjCPropertyQueryKind QueryKind) const; - void collectPropertiesToImplement(PropertyMap &PM, - PropertyDeclOrder &PO) const override; + void collectPropertiesToImplement(PropertyMap &PM) const override; /// isSuperClassOf - Return true if this class is the specified class or is a /// super class of the specified interface class. @@ -1895,10 +1914,17 @@ public: const Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; } + /// Get precomputed ODRHash or add a new one. + unsigned getODRHash(); + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCInterface; } private: + /// True if a valid hash is stored in ODRHash. + bool hasODRHash() const; + void setHasODRHash(bool HasHash); + const ObjCInterfaceDecl *findInterfaceWithDesignatedInitializers() const; bool inheritsDesignatedInitializers() const; }; @@ -1949,12 +1975,22 @@ public: /// in; this is either the interface where the ivar was declared, or the /// interface the ivar is conceptually a part of in the case of synthesized /// ivars. - const ObjCInterfaceDecl *getContainingInterface() const; + ObjCInterfaceDecl *getContainingInterface(); + const ObjCInterfaceDecl *getContainingInterface() const { + return const_cast<ObjCIvarDecl *>(this)->getContainingInterface(); + } ObjCIvarDecl *getNextIvar() { return NextIvar; } const ObjCIvarDecl *getNextIvar() const { return NextIvar; } void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; } + ObjCIvarDecl *getCanonicalDecl() override { + return cast<ObjCIvarDecl>(FieldDecl::getCanonicalDecl()); + } + const ObjCIvarDecl *getCanonicalDecl() const { + return const_cast<ObjCIvarDecl *>(this)->getCanonicalDecl(); + } + void setAccessControl(AccessControl ac) { DeclAccess = ac; } AccessControl getAccessControl() const { return AccessControl(DeclAccess); } @@ -1980,7 +2016,9 @@ private: ObjCIvarDecl *NextIvar = nullptr; // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum + LLVM_PREFERRED_TYPE(AccessControl) unsigned DeclAccess : 3; + LLVM_PREFERRED_TYPE(bool) unsigned Synthesized : 1; }; @@ -2045,6 +2083,13 @@ class ObjCProtocolDecl : public ObjCContainerDecl, /// Referenced protocols ObjCProtocolList ReferencedProtocols; + + /// Tracks whether a ODR hash has been computed for this protocol. + LLVM_PREFERRED_TYPE(bool) + unsigned HasODRHash : 1; + + /// A hash of parts of the class to help in ODR checking. + unsigned ODRHash = 0; }; /// Contains a pointer to the data associated with this class, @@ -2081,10 +2126,15 @@ class ObjCProtocolDecl : public ObjCContainerDecl, return getMostRecentDecl(); } + /// True if a valid hash is stored in ODRHash. + bool hasODRHash() const; + void setHasODRHash(bool HasHash); + public: friend class ASTDeclReader; friend class ASTDeclWriter; friend class ASTReader; + friend class ODRDiagsEmitter; static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, @@ -2209,6 +2259,13 @@ public: /// Starts the definition of this Objective-C protocol. void startDefinition(); + /// Starts the definition without sharing it with other redeclarations. + /// Such definition shouldn't be used for anything but only to compare if + /// a duplicate is compatible with previous definition or if it is + /// a distinct duplicate. + void startDuplicateDefinitionForComparison(); + void mergeDuplicateDefinitionWithCommon(const ObjCProtocolDecl *Definition); + /// Produce a name to be used for protocol's metadata. It comes either via /// objc_runtime_name attribute or protocol name. StringRef getObjCRuntimeNameAsString() const; @@ -2234,13 +2291,15 @@ public: ObjCProtocolDecl *getCanonicalDecl() override { return getFirstDecl(); } const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); } - void collectPropertiesToImplement(PropertyMap &PM, - PropertyDeclOrder &PO) const override; + void collectPropertiesToImplement(PropertyMap &PM) const override; void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property, ProtocolPropertySet &PS, PropertyDeclOrder &PO) const; + /// Get precomputed ODRHash or add a new one. + unsigned getODRHash(); + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCProtocol; } }; @@ -2549,9 +2608,11 @@ class ObjCImplementationDecl : public ObjCImplDecl { /// Do the ivars of this class require initialization other than /// zero-initialization? + LLVM_PREFERRED_TYPE(bool) bool HasNonZeroConstructors : 1; /// Do the ivars of this class require non-trivial destruction? + LLVM_PREFERRED_TYPE(bool) bool HasDestructors : 1; ObjCImplementationDecl(DeclContext *DC, @@ -2876,15 +2937,16 @@ ObjCInterfaceDecl::filtered_category_iterator<Filter>::operator++() { } inline bool ObjCInterfaceDecl::isVisibleCategory(ObjCCategoryDecl *Cat) { - return Cat->isUnconditionallyVisible(); + return !Cat->isInvalidDecl() && Cat->isUnconditionallyVisible(); } inline bool ObjCInterfaceDecl::isVisibleExtension(ObjCCategoryDecl *Cat) { - return Cat->IsClassExtension() && Cat->isUnconditionallyVisible(); + return !Cat->isInvalidDecl() && Cat->IsClassExtension() && + Cat->isUnconditionallyVisible(); } inline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) { - return Cat->IsClassExtension(); + return !Cat->isInvalidDecl() && Cat->IsClassExtension(); } } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclObjCCommon.h b/contrib/llvm-project/clang/include/clang/AST/DeclObjCCommon.h index 5f03bce6e9a8..42c97204a613 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclObjCCommon.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclObjCCommon.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_DECLOBJC_COMMON_H -#define LLVM_CLANG_AST_DECLOBJC_COMMON_H +#ifndef LLVM_CLANG_AST_DECLOBJCCOMMON_H +#define LLVM_CLANG_AST_DECLOBJCCOMMON_H namespace clang { @@ -52,4 +52,4 @@ enum { } // namespace clang -#endif // LLVM_CLANG_AST_DECLOBJC_COMMON_H +#endif // LLVM_CLANG_AST_DECLOBJCCOMMON_H diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclOpenMP.h b/contrib/llvm-project/clang/include/clang/AST/DeclOpenMP.h index 4aa5bde92e12..73725e6e8566 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclOpenMP.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclOpenMP.h @@ -34,7 +34,7 @@ template <typename U> class OMPDeclarativeDirective : public U { /// Get the clauses storage. MutableArrayRef<OMPClause *> getClauses() { if (!Data) - return llvm::None; + return std::nullopt; return Data->getClauses(); } @@ -90,7 +90,7 @@ public: ArrayRef<OMPClause *> clauses() const { if (!Data) - return llvm::None; + return std::nullopt; return Data->getClauses(); } }; @@ -118,12 +118,12 @@ class OMPThreadPrivateDecl final : public OMPDeclarativeDirective<Decl> { ArrayRef<const Expr *> getVars() const { auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); - return llvm::makeArrayRef(Storage, Data->getNumChildren()); + return llvm::ArrayRef(Storage, Data->getNumChildren()); } MutableArrayRef<Expr *> getVars() { auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); - return llvm::makeMutableArrayRef(Storage, Data->getNumChildren()); + return llvm::MutableArrayRef(Storage, Data->getNumChildren()); } void setVars(ArrayRef<Expr *> VL); @@ -158,6 +158,12 @@ public: static bool classofKind(Kind K) { return K == OMPThreadPrivate; } }; +enum class OMPDeclareReductionInitKind { + Call, // Initialized by function call. + Direct, // omp_priv(<expr>) + Copy // omp_priv = <expr> +}; + /// This represents '#pragma omp declare reduction ...' directive. /// For example, in the following, declared reduction 'foo' for types 'int' and /// 'float': @@ -171,14 +177,7 @@ public: class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext { // This class stores some data in DeclContext::OMPDeclareReductionDeclBits // to save some space. Use the provided accessors to access it. -public: - enum InitKind { - CallInit, // Initialized by function call. - DirectInit, // omp_priv(<expr>) - CopyInit // omp_priv = <expr> - }; -private: friend class ASTDeclReader; /// Combiner for declare reduction construct. Expr *Combiner = nullptr; @@ -239,8 +238,9 @@ public: Expr *getInitializer() { return Initializer; } const Expr *getInitializer() const { return Initializer; } /// Get initializer kind. - InitKind getInitializerKind() const { - return static_cast<InitKind>(OMPDeclareReductionDeclBits.InitializerKind); + OMPDeclareReductionInitKind getInitializerKind() const { + return static_cast<OMPDeclareReductionInitKind>( + OMPDeclareReductionDeclBits.InitializerKind); } /// Get Orig variable of the initializer. Expr *getInitOrig() { return Orig; } @@ -249,9 +249,9 @@ public: Expr *getInitPriv() { return Priv; } const Expr *getInitPriv() const { return Priv; } /// Set initializer expression for the declare reduction construct. - void setInitializer(Expr *E, InitKind IK) { + void setInitializer(Expr *E, OMPDeclareReductionInitKind IK) { Initializer = E; - OMPDeclareReductionDeclBits.InitializerKind = IK; + OMPDeclareReductionDeclBits.InitializerKind = llvm::to_underlying(IK); } /// Set initializer Orig and Priv vars. void setInitializerData(Expr *OrigE, Expr *PrivE) { @@ -481,12 +481,12 @@ class OMPAllocateDecl final : public OMPDeclarativeDirective<Decl> { ArrayRef<const Expr *> getVars() const { auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); - return llvm::makeArrayRef(Storage, Data->getNumChildren()); + return llvm::ArrayRef(Storage, Data->getNumChildren()); } MutableArrayRef<Expr *> getVars() { auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); - return llvm::makeMutableArrayRef(Storage, Data->getNumChildren()); + return llvm::MutableArrayRef(Storage, Data->getNumChildren()); } void setVars(ArrayRef<Expr *> VL); diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclTemplate.h b/contrib/llvm-project/clang/include/clang/AST/DeclTemplate.h index cbaa287f225a..832ad2de6b08 100755 --- a/contrib/llvm-project/clang/include/clang/AST/DeclTemplate.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclTemplate.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_DECLTEMPLATE_H #include "clang/AST/ASTConcept.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" @@ -38,6 +39,7 @@ #include <cstddef> #include <cstdint> #include <iterator> +#include <optional> #include <utility> namespace clang { @@ -81,13 +83,16 @@ class TemplateParameterList final /// Whether this template parameter list contains an unexpanded parameter /// pack. + LLVM_PREFERRED_TYPE(bool) unsigned ContainsUnexpandedParameterPack : 1; /// Whether this template parameter list has a requires clause. + LLVM_PREFERRED_TYPE(bool) unsigned HasRequiresClause : 1; /// Whether any of the template parameters has constrained-parameter /// constraint-expression. + LLVM_PREFERRED_TYPE(bool) unsigned HasConstrainedParameters : 1; protected: @@ -115,6 +120,8 @@ public: SourceLocation RAngleLoc, Expr *RequiresClause); + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) const; + /// Iterates through the template parameters in this list. using iterator = NamedDecl **; @@ -128,11 +135,9 @@ public: unsigned size() const { return NumParams; } - ArrayRef<NamedDecl*> asArray() { - return llvm::makeArrayRef(begin(), end()); - } + ArrayRef<NamedDecl *> asArray() { return llvm::ArrayRef(begin(), end()); } ArrayRef<const NamedDecl*> asArray() const { - return llvm::makeArrayRef(begin(), size()); + return llvm::ArrayRef(begin(), size()); } NamedDecl* getParam(unsigned Idx) { @@ -203,7 +208,8 @@ public: void print(raw_ostream &Out, const ASTContext &Context, const PrintingPolicy &Policy, bool OmitTemplateKW = false) const; - static bool shouldIncludeTypeForArgument(const TemplateParameterList *TPL, + static bool shouldIncludeTypeForArgument(const PrintingPolicy &Policy, + const TemplateParameterList *TPL, unsigned Idx); }; @@ -272,8 +278,7 @@ public: /// /// This operation assumes that the input argument list outlives it. /// This takes the list as a pointer to avoid looking like a copy - /// constructor, since this really really isn't safe to use that - /// way. + /// constructor, since this really isn't safe to use that way. explicit TemplateArgumentList(const TemplateArgumentList *Other) : Arguments(Other->data()), NumArguments(Other->size()) {} @@ -288,7 +293,7 @@ public: /// Produce this as an array ref. ArrayRef<TemplateArgument> asArray() const { - return llvm::makeArrayRef(data(), size()); + return llvm::ArrayRef(data(), size()); } /// Retrieve the number of template arguments in this @@ -372,11 +377,20 @@ public: /// Set that the default argument was inherited from another parameter. void setInherited(const ASTContext &C, ParmDecl *InheritedFrom) { - assert(!isInherited() && "default argument already inherited"); InheritedFrom = getParmOwningDefaultArg(InheritedFrom); if (!isSet()) ValueOrInherited = InheritedFrom; - else + else if ([[maybe_unused]] auto *D = + ValueOrInherited.template dyn_cast<ParmDecl *>()) { + assert(C.isSameDefaultTemplateArgument(D, InheritedFrom)); + ValueOrInherited = + new (allocateDefaultArgStorageChain(C)) Chain{InheritedFrom, get()}; + } else if (auto *Inherited = + ValueOrInherited.template dyn_cast<Chain *>()) { + assert(C.isSameDefaultTemplateArgument(Inherited->PrevDeclWithDefaultArg, + InheritedFrom)); + Inherited->PrevDeclWithDefaultArg = InheritedFrom; + } else ValueOrInherited = new (allocateDefaultArgStorageChain(C)) Chain{InheritedFrom, ValueOrInherited.template get<ArgType>()}; } @@ -430,6 +444,9 @@ public: /// Get the underlying, templated declaration. NamedDecl *getTemplatedDecl() const { return TemplatedDecl; } + // Should a specialization behave like an alias for another type. + bool isTypeAlias() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -446,18 +463,17 @@ protected: NamedDecl *TemplatedDecl; TemplateParameterList *TemplateParams; +public: void setTemplateParameters(TemplateParameterList *TParams) { TemplateParams = TParams; } -public: - /// Initialize the underlying templated declaration and - /// template parameters. - void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) { - assert(!TemplatedDecl && "TemplatedDecl already set!"); - assert(!TemplateParams && "TemplateParams already set!"); - TemplatedDecl = templatedDecl; - TemplateParams = templateParams; + /// Initialize the underlying templated declaration. + void init(NamedDecl *NewTemplatedDecl) { + if (TemplatedDecl) + assert(TemplatedDecl == NewTemplatedDecl && "Inconsistent TemplatedDecl"); + else + TemplatedDecl = NewTemplatedDecl; } }; @@ -497,7 +513,7 @@ private: TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs, const ASTTemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI, MemberSpecializationInfo *MSInfo) - : Function(FD, MSInfo ? 1 : 0), Template(Template, TSK - 1), + : Function(FD, MSInfo ? true : false), Template(Template, TSK - 1), TemplateArguments(TemplateArgs), TemplateArgumentsAsWritten(TemplateArgsAsWritten), PointOfInstantiation(POI) { @@ -570,7 +586,7 @@ public: /// \code /// template<typename> struct A { /// template<typename> void f(); - /// template<> void f<int>(); // ClassScopeFunctionSpecializationDecl + /// template<> void f<int>(); /// }; /// \endcode /// @@ -606,7 +622,7 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs, - ASTContext &Context) { + const ASTContext &Context) { ID.AddInteger(TemplateArgs.size()); for (const TemplateArgument &TemplateArg : TemplateArgs) TemplateArg.Profile(ID, Context); @@ -669,78 +685,48 @@ public: /// Provides information about a dependent function-template /// specialization declaration. /// -/// Since explicit function template specialization and instantiation -/// declarations can only appear in namespace scope, and you can only -/// specialize a member of a fully-specialized class, the only way to -/// get one of these is in a friend declaration like the following: +/// This is used for function templates explicit specializations declared +/// within class templates: +/// +/// \code +/// template<typename> struct A { +/// template<typename> void f(); +/// template<> void f<int>(); // DependentFunctionTemplateSpecializationInfo +/// }; +/// \endcode +/// +/// As well as dependent friend declarations naming function template +/// specializations declared within class templates: /// /// \code /// template \<class T> void foo(T); /// template \<class T> class A { -/// friend void foo<>(T); +/// friend void foo<>(T); // DependentFunctionTemplateSpecializationInfo /// }; /// \endcode class DependentFunctionTemplateSpecializationInfo final : private llvm::TrailingObjects<DependentFunctionTemplateSpecializationInfo, - TemplateArgumentLoc, FunctionTemplateDecl *> { - /// The number of potential template candidates. - unsigned NumTemplates; - - /// The number of template arguments. - unsigned NumArgs; - - /// The locations of the left and right angle brackets. - SourceRange AngleLocs; + friend TrailingObjects; - size_t numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const { - return NumArgs; - } - size_t numTrailingObjects(OverloadToken<FunctionTemplateDecl *>) const { - return NumTemplates; - } + /// The number of candidates for the primary template. + unsigned NumCandidates; DependentFunctionTemplateSpecializationInfo( - const UnresolvedSetImpl &Templates, - const TemplateArgumentListInfo &TemplateArgs); + const UnresolvedSetImpl &Candidates, + const ASTTemplateArgumentListInfo *TemplateArgsWritten); public: - friend TrailingObjects; + /// The template arguments as written in the sources, if provided. + const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten; static DependentFunctionTemplateSpecializationInfo * - Create(ASTContext &Context, const UnresolvedSetImpl &Templates, - const TemplateArgumentListInfo &TemplateArgs); + Create(ASTContext &Context, const UnresolvedSetImpl &Candidates, + const TemplateArgumentListInfo *TemplateArgs); - /// Returns the number of function templates that this might - /// be a specialization of. - unsigned getNumTemplates() const { return NumTemplates; } - - /// Returns the i'th template candidate. - FunctionTemplateDecl *getTemplate(unsigned I) const { - assert(I < getNumTemplates() && "template index out of range"); - return getTrailingObjects<FunctionTemplateDecl *>()[I]; - } - - /// Returns the explicit template arguments that were given. - const TemplateArgumentLoc *getTemplateArgs() const { - return getTrailingObjects<TemplateArgumentLoc>(); - } - - /// Returns the number of explicit template arguments that were given. - unsigned getNumTemplateArgs() const { return NumArgs; } - - /// Returns the nth template argument. - const TemplateArgumentLoc &getTemplateArg(unsigned I) const { - assert(I < getNumTemplateArgs() && "template arg index out of range"); - return getTemplateArgs()[I]; - } - - SourceLocation getLAngleLoc() const { - return AngleLocs.getBegin(); - } - - SourceLocation getRAngleLoc() const { - return AngleLocs.getEnd(); + /// Returns the candidates for the primary function template. + ArrayRef<FunctionTemplateDecl *> getCandidates() const { + return {getTrailingObjects<FunctionTemplateDecl *>(), NumCandidates}; } }; @@ -831,6 +817,15 @@ protected: /// The first value in the array is the number of specializations/partial /// specializations that follow. uint32_t *LazySpecializations = nullptr; + + /// The set of "injected" template arguments used within this + /// template. + /// + /// This pointer refers to the template arguments (there are as + /// many template arguments as template parameters) for the + /// template, and is allocated lazily, since most templates do not + /// require the use of this information. + TemplateArgument *InjectedArgs = nullptr; }; /// Pointer to the common data shared by all declarations of this @@ -938,6 +933,14 @@ public: getCommonPtr()->InstantiatedFromMember.setPointer(TD); } + /// Retrieve the "injected" template arguments that correspond to the + /// template parameters of this template. + /// + /// Although the C++ standard has no notion of the "injected" template + /// arguments for a template, the notion is convenient when + /// we need to perform substitutions inside the definition of a template. + ArrayRef<TemplateArgument> getInjectedTemplateArgs(); + using redecl_range = redeclarable_base::redecl_range; using redecl_iterator = redeclarable_base::redecl_iterator; @@ -982,15 +985,6 @@ protected: /// template, including explicit specializations and instantiations. llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> Specializations; - /// The set of "injected" template arguments used within this - /// function template. - /// - /// This pointer refers to the template arguments (there are as - /// many template arguments as template parameaters) for the function - /// template, and is allocated lazily, since most function templates do not - /// require the use of this information. - TemplateArgument *InjectedArgs = nullptr; - Common() = default; }; @@ -1090,21 +1084,12 @@ public: return makeSpecIterator(getSpecializations(), true); } - /// Retrieve the "injected" template arguments that correspond to the - /// template parameters of this function template. - /// - /// Although the C++ standard has no notion of the "injected" template - /// arguments for a function template, the notion is convenient when - /// we need to perform substitutions inside the definition of a function - /// template. - ArrayRef<TemplateArgument> getInjectedTemplateArgs(); - /// Return whether this function template is an abbreviated function template, /// e.g. `void foo(auto x)` or `template<typename T> void foo(auto x)` bool isAbbreviated() const { // Since the invented template parameters generated from 'auto' parameters // are either appended to the end of the explicit template parameter list or - // form a new template paramter list, we can simply observe the last + // form a new template parameter list, we can simply observe the last // parameter to determine if such a thing happened. const TemplateParameterList *TPL = getTemplateParameters(); return TPL->getParam(TPL->size() - 1)->isImplicit(); @@ -1143,23 +1128,40 @@ public: /// parameters and is not part of the Decl hierarchy. Just a facility. class TemplateParmPosition { protected: - // FIXME: These probably don't need to be ints. int:5 for depth, int:8 for - // position? Maybe? - unsigned Depth; - unsigned Position; + enum { DepthWidth = 20, PositionWidth = 12 }; + unsigned Depth : DepthWidth; + unsigned Position : PositionWidth; - TemplateParmPosition(unsigned D, unsigned P) : Depth(D), Position(P) {} + static constexpr unsigned MaxDepth = (1U << DepthWidth) - 1; + static constexpr unsigned MaxPosition = (1U << PositionWidth) - 1; + + TemplateParmPosition(unsigned D, unsigned P) : Depth(D), Position(P) { + // The input may fill maximum values to show that it is invalid. + // Add one here to convert it to zero. + assert((D + 1) <= MaxDepth && + "The depth of template parmeter position is more than 2^20!"); + assert((P + 1) <= MaxPosition && + "The position of template parmeter position is more than 2^12!"); + } public: TemplateParmPosition() = delete; /// Get the nesting depth of the template parameter. unsigned getDepth() const { return Depth; } - void setDepth(unsigned D) { Depth = D; } + void setDepth(unsigned D) { + assert((D + 1) <= MaxDepth && + "The depth of template parmeter position is more than 2^20!"); + Depth = D; + } /// Get the position of the template parameter within its parameter list. unsigned getPosition() const { return Position; } - void setPosition(unsigned P) { Position = P; } + void setPosition(unsigned P) { + assert((P + 1) <= MaxPosition && + "The position of template parmeter position is more than 2^12!"); + Position = P; + } /// Get the index of the template parameter within its parameter list. unsigned getIndex() const { return Position; } @@ -1189,10 +1191,10 @@ class TemplateTypeParmDecl final : public TypeDecl, /// Whether the type constraint has been initialized. This can be false if the /// constraint was not initialized yet or if there was an error forming the - /// type constriant. + /// type constraint. bool TypeConstraintInitialized : 1; - /// Whether this non-type template parameter is an "expanded" + /// Whether this type template parameter is an "expanded" /// parameter pack, meaning that its type is a pack expansion and we /// already know the set of types that expansion expands to. bool ExpandedParameterPack : 1; @@ -1206,23 +1208,20 @@ class TemplateTypeParmDecl final : public TypeDecl, DefArgStorage DefaultArgument; TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - bool Typename, bool HasTypeConstraint, - Optional<unsigned> NumExpanded) + SourceLocation IdLoc, IdentifierInfo *Id, bool Typename, + bool HasTypeConstraint, + std::optional<unsigned> NumExpanded) : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename), - HasTypeConstraint(HasTypeConstraint), TypeConstraintInitialized(false), - ExpandedParameterPack(NumExpanded), - NumExpanded(NumExpanded ? *NumExpanded : 0) {} + HasTypeConstraint(HasTypeConstraint), TypeConstraintInitialized(false), + ExpandedParameterPack(NumExpanded), + NumExpanded(NumExpanded.value_or(0)) {} public: - static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC, - SourceLocation KeyLoc, - SourceLocation NameLoc, - unsigned D, unsigned P, - IdentifierInfo *Id, bool Typename, - bool ParameterPack, - bool HasTypeConstraint = false, - Optional<unsigned> NumExpanded = None); + static TemplateTypeParmDecl * + Create(const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc, + SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id, + bool Typename, bool ParameterPack, bool HasTypeConstraint = false, + std::optional<unsigned> NumExpanded = std::nullopt); static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, unsigned ID); static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, @@ -1344,10 +1343,7 @@ public: nullptr; } - void setTypeConstraint(NestedNameSpecifierLoc NNS, - DeclarationNameInfo NameInfo, NamedDecl *FoundDecl, - ConceptDecl *CD, - const ASTTemplateArgumentListInfo *ArgsAsWritten, + void setTypeConstraint(ConceptReference *CR, Expr *ImmediatelyDeclaredConstraint); /// Determine whether this template parameter has a type-constraint. @@ -1358,7 +1354,7 @@ public: /// \brief Get the associated-constraints of this template parameter. /// This will either be the immediately-introduced constraint or empty. /// - /// Use this instead of getConstraintExpression for concepts APIs that + /// Use this instead of getTypeConstraint for concepts APIs that /// accept an ArrayRef of constraint expressions. void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const { if (HasTypeConstraint) @@ -1840,7 +1836,7 @@ class ClassTemplateSpecializationDecl SourceLocation PointOfInstantiation; /// The kind of specialization this declaration refers to. - /// Really a value of type TemplateSpecializationKind. + LLVM_PREFERRED_TYPE(TemplateSpecializationKind) unsigned SpecializationKind : 3; protected: @@ -2054,7 +2050,7 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs, - ASTContext &Context) { + const ASTContext &Context) { ID.AddInteger(TemplateArgs.size()); for (const TemplateArgument &TemplateArg : TemplateArgs) TemplateArg.Profile(ID, Context); @@ -2230,7 +2226,7 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs, - TemplateParameterList *TPL, ASTContext &Context); + TemplateParameterList *TPL, const ASTContext &Context); static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2280,9 +2276,15 @@ protected: return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); } + void setCommonPtr(Common *C) { + RedeclarableTemplateDecl::Common = C; + } + public: + friend class ASTDeclReader; friend class ASTDeclWriter; + friend class TemplateDeclInstantiator; /// Load any lazily-loaded specializations from the external source. void LoadLazySpecializations() const; @@ -2457,10 +2459,10 @@ private: SourceLocation FriendLoc; FriendTemplateDecl(DeclContext *DC, SourceLocation Loc, - MutableArrayRef<TemplateParameterList *> Params, + TemplateParameterList **Params, unsigned NumParams, FriendUnion Friend, SourceLocation FriendLoc) - : Decl(Decl::FriendTemplate, DC, Loc), NumParams(Params.size()), - Params(Params.data()), Friend(Friend), FriendLoc(FriendLoc) {} + : Decl(Decl::FriendTemplate, DC, Loc), NumParams(NumParams), + Params(Params), Friend(Friend), FriendLoc(FriendLoc) {} FriendTemplateDecl(EmptyShell Empty) : Decl(Decl::FriendTemplate, Empty) {} @@ -2580,70 +2582,6 @@ public: static bool classofKind(Kind K) { return K == TypeAliasTemplate; } }; -/// Declaration of a function specialization at template class scope. -/// -/// For example: -/// \code -/// template <class T> -/// class A { -/// template <class U> void foo(U a) { } -/// template<> void foo(int a) { } -/// } -/// \endcode -/// -/// "template<> foo(int a)" will be saved in Specialization as a normal -/// CXXMethodDecl. Then during an instantiation of class A, it will be -/// transformed into an actual function specialization. -/// -/// FIXME: This is redundant; we could store the same information directly on -/// the CXXMethodDecl as a DependentFunctionTemplateSpecializationInfo. -class ClassScopeFunctionSpecializationDecl : public Decl { - CXXMethodDecl *Specialization; - const ASTTemplateArgumentListInfo *TemplateArgs; - - ClassScopeFunctionSpecializationDecl( - DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD, - const ASTTemplateArgumentListInfo *TemplArgs) - : Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc), - Specialization(FD), TemplateArgs(TemplArgs) {} - - ClassScopeFunctionSpecializationDecl(EmptyShell Empty) - : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {} - - virtual void anchor(); - -public: - friend class ASTDeclReader; - friend class ASTDeclWriter; - - CXXMethodDecl *getSpecialization() const { return Specialization; } - bool hasExplicitTemplateArgs() const { return TemplateArgs; } - const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { - return TemplateArgs; - } - - static ClassScopeFunctionSpecializationDecl * - Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD, - bool HasExplicitTemplateArgs, - const TemplateArgumentListInfo &TemplateArgs) { - return new (C, DC) ClassScopeFunctionSpecializationDecl( - DC, Loc, FD, - HasExplicitTemplateArgs - ? ASTTemplateArgumentListInfo::Create(C, TemplateArgs) - : nullptr); - } - - static ClassScopeFunctionSpecializationDecl * - CreateDeserialized(ASTContext &Context, unsigned ID); - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - - static bool classofKind(Kind K) { - return K == Decl::ClassScopeFunctionSpecialization; - } -}; - /// Represents a variable template specialization, which refers to /// a variable template with a given set of template arguments. /// @@ -2697,19 +2635,20 @@ class VarTemplateSpecializationDecl : public VarDecl, /// The template arguments used to describe this specialization. const TemplateArgumentList *TemplateArgs; - TemplateArgumentListInfo TemplateArgsInfo; + const ASTTemplateArgumentListInfo *TemplateArgsInfo = nullptr; /// The point where this template was instantiated (if any). SourceLocation PointOfInstantiation; /// The kind of specialization this declaration refers to. - /// Really a value of type TemplateSpecializationKind. + LLVM_PREFERRED_TYPE(TemplateSpecializationKind) unsigned SpecializationKind : 3; /// Whether this declaration is a complete definition of the /// variable template specialization. We can't otherwise tell apart /// an instantiated declaration from an instantiated definition with /// no initializer. + LLVM_PREFERRED_TYPE(bool) unsigned IsCompleteDefinition : 1; protected: @@ -2752,8 +2691,9 @@ public: // TODO: Always set this when creating the new specialization? void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo); + void setTemplateArgsInfo(const ASTTemplateArgumentListInfo *ArgsInfo); - const TemplateArgumentListInfo &getTemplateArgsInfo() const { + const ASTTemplateArgumentListInfo *getTemplateArgsInfo() const { return TemplateArgsInfo; } @@ -2898,13 +2838,15 @@ public: return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); } + SourceRange getSourceRange() const override LLVM_READONLY; + void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, TemplateArgs->asArray(), getASTContext()); } static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs, - ASTContext &Context) { + const ASTContext &Context) { ID.AddInteger(TemplateArgs.size()); for (const TemplateArgument &TemplateArg : TemplateArgs) TemplateArg.Profile(ID, Context); @@ -3055,6 +2997,8 @@ public: return First->InstantiatedFromMember.setInt(true); } + SourceRange getSourceRange() const override LLVM_READONLY; + void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(), getASTContext()); @@ -3062,7 +3006,7 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs, - TemplateParameterList *TPL, ASTContext &Context); + TemplateParameterList *TPL, const ASTContext &Context); static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -3227,7 +3171,7 @@ public: static bool classofKind(Kind K) { return K == VarTemplate; } }; -/// Declaration of a C++2a concept. +/// Declaration of a C++20 concept. class ConceptDecl : public TemplateDecl, public Mergeable<ConceptDecl> { protected: Expr *ConstraintExpr; @@ -3256,8 +3200,12 @@ public: return isa<TemplateTypeParmDecl>(getTemplateParameters()->getParam(0)); } - ConceptDecl *getCanonicalDecl() override { return getFirstDecl(); } - const ConceptDecl *getCanonicalDecl() const { return getFirstDecl(); } + ConceptDecl *getCanonicalDecl() override { + return cast<ConceptDecl>(getPrimaryMergedDecl(this)); + } + const ConceptDecl *getCanonicalDecl() const { + return const_cast<ConceptDecl *>(this)->getCanonicalDecl(); + } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -3268,6 +3216,40 @@ public: friend class ASTDeclWriter; }; +// An implementation detail of ConceptSpecialicationExpr that holds the template +// arguments, so we can later use this to reconstitute the template arguments +// during constraint checking. +class ImplicitConceptSpecializationDecl final + : public Decl, + private llvm::TrailingObjects<ImplicitConceptSpecializationDecl, + TemplateArgument> { + unsigned NumTemplateArgs; + + ImplicitConceptSpecializationDecl(DeclContext *DC, SourceLocation SL, + ArrayRef<TemplateArgument> ConvertedArgs); + ImplicitConceptSpecializationDecl(EmptyShell Empty, unsigned NumTemplateArgs); + +public: + static ImplicitConceptSpecializationDecl * + Create(const ASTContext &C, DeclContext *DC, SourceLocation SL, + ArrayRef<TemplateArgument> ConvertedArgs); + static ImplicitConceptSpecializationDecl * + CreateDeserialized(const ASTContext &C, unsigned ID, + unsigned NumTemplateArgs); + + ArrayRef<TemplateArgument> getTemplateArguments() const { + return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(), + NumTemplateArgs); + } + void setTemplateArguments(ArrayRef<TemplateArgument> Converted); + + static bool classofKind(Kind K) { return K == ImplicitConceptSpecialization; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + + friend TrailingObjects; + friend class ASTDeclReader; +}; + /// A template parameter object. /// /// Template parameter objects represent values of class type used as template @@ -3305,14 +3287,17 @@ private: public: /// Print this template parameter object in a human-readable format. - void printName(llvm::raw_ostream &OS) const override; + void printName(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const override; /// Print this object as an equivalent expression. void printAsExpr(llvm::raw_ostream &OS) const; + void printAsExpr(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const; /// Print this object as an initializer suitable for a variable of the /// object's type. void printAsInit(llvm::raw_ostream &OS) const; + void printAsInit(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const; const APValue &getValue() const { return Value; } @@ -3365,7 +3350,7 @@ inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) { /// /// In \c A<int,int>::B, \c NTs and \c TTs have expanded pack size 2, and \c Us /// is not a pack expansion, so returns an empty Optional. -inline Optional<unsigned> getExpandedPackSize(const NamedDecl *Param) { +inline std::optional<unsigned> getExpandedPackSize(const NamedDecl *Param) { if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { if (TTP->isExpandedParameterPack()) return TTP->getNumExpansionParameters(); @@ -3381,9 +3366,13 @@ inline Optional<unsigned> getExpandedPackSize(const NamedDecl *Param) { return TTP->getNumExpansionTemplateParameters(); } - return None; + return std::nullopt; } +/// Internal helper used by Subst* nodes to retrieve the parameter list +/// for their AssociatedDecl. +TemplateParameterList *getReplacedTemplateParameterList(Decl *D); + } // namespace clang #endif // LLVM_CLANG_AST_DECLTEMPLATE_H diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclarationName.h b/contrib/llvm-project/clang/include/clang/AST/DeclarationName.h index 38da6fc727fb..c9b01dc53964 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclarationName.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclarationName.h @@ -21,6 +21,7 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/type_traits.h" #include <cassert> @@ -34,11 +35,9 @@ class ASTContext; template <typename> class CanQual; class DeclarationName; class DeclarationNameTable; -class MultiKeywordSelector; struct PrintingPolicy; class TemplateDecl; class TypeSourceInfo; -class UsingDirectiveDecl; using CanQualType = CanQual<Type>; @@ -119,14 +118,14 @@ class alignas(IdentifierInfoAlignment) CXXLiteralOperatorIdName friend class clang::DeclarationName; friend class clang::DeclarationNameTable; - IdentifierInfo *ID; + const IdentifierInfo *ID; /// Extra information associated with this operator name that /// can be used by the front end. All bits are really needed /// so it is not possible to stash something in the low order bits. void *FETokenInfo; - CXXLiteralOperatorIdName(IdentifierInfo *II) + CXXLiteralOperatorIdName(const IdentifierInfo *II) : DeclarationNameExtra(CXXLiteralOperatorName), ID(II), FETokenInfo(nullptr) {} @@ -194,6 +193,13 @@ class DeclarationName { "The various classes that DeclarationName::Ptr can point to" " must be at least aligned to 8 bytes!"); + static_assert( + std::is_same<std::underlying_type_t<StoredNameKind>, + std::underlying_type_t< + detail::DeclarationNameExtra::ExtraKind>>::value, + "The various enums used to compute values for NameKind should " + "all have the same underlying type"); + public: /// The kind of the name stored in this DeclarationName. /// The first 7 enumeration values are stored inline and correspond @@ -207,15 +213,18 @@ public: CXXDestructorName = StoredCXXDestructorName, CXXConversionFunctionName = StoredCXXConversionFunctionName, CXXOperatorName = StoredCXXOperatorName, - CXXDeductionGuideName = UncommonNameKindOffset + - detail::DeclarationNameExtra::CXXDeductionGuideName, - CXXLiteralOperatorName = - UncommonNameKindOffset + - detail::DeclarationNameExtra::CXXLiteralOperatorName, - CXXUsingDirective = UncommonNameKindOffset + - detail::DeclarationNameExtra::CXXUsingDirective, - ObjCMultiArgSelector = UncommonNameKindOffset + - detail::DeclarationNameExtra::ObjCMultiArgSelector + CXXDeductionGuideName = llvm::addEnumValues( + UncommonNameKindOffset, + detail::DeclarationNameExtra::CXXDeductionGuideName), + CXXLiteralOperatorName = llvm::addEnumValues( + UncommonNameKindOffset, + detail::DeclarationNameExtra::CXXLiteralOperatorName), + CXXUsingDirective = + llvm::addEnumValues(UncommonNameKindOffset, + detail::DeclarationNameExtra::CXXUsingDirective), + ObjCMultiArgSelector = + llvm::addEnumValues(UncommonNameKindOffset, + detail::DeclarationNameExtra::ObjCMultiArgSelector), }; private: @@ -353,7 +362,8 @@ public: } /// Construct a declaration name from an Objective-C selector. - DeclarationName(Selector Sel) : Ptr(Sel.InfoPtr) {} + DeclarationName(Selector Sel) + : Ptr(reinterpret_cast<uintptr_t>(Sel.InfoPtr.getOpaqueValue())) {} /// Returns the name for all C++ using-directives. static DeclarationName getUsingDirectiveName() { @@ -469,7 +479,7 @@ public: /// If this name is the name of a literal operator, /// retrieve the identifier associated with it. - IdentifierInfo *getCXXLiteralIdentifier() const { + const IdentifierInfo *getCXXLiteralIdentifier() const { if (getNameKind() == CXXLiteralOperatorName) { assert(getPtr() && "getCXXLiteralIdentifier on a null DeclarationName!"); return castAsCXXLiteralOperatorIdName()->ID; @@ -641,7 +651,7 @@ public: } /// Get the name of the literal operator function with II as the identifier. - DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II); + DeclarationName getCXXLiteralOperatorName(const IdentifierInfo *II); }; /// DeclarationNameLoc - Additional source/type location info @@ -754,7 +764,7 @@ public: }; /// DeclarationNameInfo - A collector data type for bundling together -/// a DeclarationName and the correspnding source/type location info. +/// a DeclarationName and the corresponding source/type location info. struct DeclarationNameInfo { private: /// Name - The declaration name, also encoding name kind. @@ -932,7 +942,7 @@ class AssumedTemplateStorage : public UncommonTemplateNameStorage { friend class ASTContext; AssumedTemplateStorage(DeclarationName Name) - : UncommonTemplateNameStorage(Assumed, 0), Name(Name) {} + : UncommonTemplateNameStorage(Assumed, 0, 0), Name(Name) {} DeclarationName Name; public: diff --git a/contrib/llvm-project/clang/include/clang/AST/DependenceFlags.h b/contrib/llvm-project/clang/include/clang/AST/DependenceFlags.h index 62efdb4ce6e4..3b3c1afb096a 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DependenceFlags.h +++ b/contrib/llvm-project/clang/include/clang/AST/DependenceFlags.h @@ -130,6 +130,14 @@ public: // Dependence that is propagated syntactically, regardless of semantics. Syntactic = UnexpandedPack | Instantiation | Error, + // Dependence that is propagated semantically, even in cases where the + // type doesn't syntactically appear. This currently excludes only + // UnexpandedPack. Even though Instantiation dependence is also notionally + // syntactic, we also want to propagate it semantically because anything + // that semantically depends on an instantiation-dependent entity should + // always be instantiated when that instantiation-dependent entity is. + Semantic = + Instantiation | Type | Value | Dependent | Error | VariablyModified, LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified) }; @@ -175,6 +183,14 @@ public: return Result; } + /// Extract the semantic portions of this type's dependence that apply even + /// to uses where the type does not appear syntactically. + Dependence semantic() { + Dependence Result = *this; + Result.V &= Semantic; + return Result; + } + TypeDependence type() const { return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) | translate(V, Instantiation, TypeDependence::Instantiation) | @@ -231,7 +247,10 @@ private: inline ExprDependence toExprDependence(TemplateArgumentDependence TA) { return Dependence(TA).expr(); } -inline ExprDependence toExprDependence(TypeDependence D) { +inline ExprDependence toExprDependenceForImpliedType(TypeDependence D) { + return Dependence(D).semantic().expr(); +} +inline ExprDependence toExprDependenceAsWritten(TypeDependence D) { return Dependence(D).expr(); } // Note: it's often necessary to strip `Dependent` from qualifiers. @@ -269,6 +288,9 @@ inline TypeDependence toTypeDependence(TemplateArgumentDependence D) { inline TypeDependence toSyntacticDependence(TypeDependence D) { return Dependence(D).syntactic().type(); } +inline TypeDependence toSemanticDependence(TypeDependence D) { + return Dependence(D).semantic().type(); +} inline NestedNameSpecifierDependence toNestedNameSpecifierDependendence(TypeDependence D) { diff --git a/contrib/llvm-project/clang/include/clang/AST/DependentDiagnostic.h b/contrib/llvm-project/clang/include/clang/AST/DependentDiagnostic.h index 18276d54d540..cadf97062004 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DependentDiagnostic.h +++ b/contrib/llvm-project/clang/include/clang/AST/DependentDiagnostic.h @@ -113,7 +113,9 @@ private: struct { SourceLocation Loc; + LLVM_PREFERRED_TYPE(AccessSpecifier) unsigned Access : 2; + LLVM_PREFERRED_TYPE(bool) unsigned IsMember : 1; NamedDecl *TargetDecl; CXXRecordDecl *NamingClass; diff --git a/contrib/llvm-project/clang/include/clang/AST/Expr.h b/contrib/llvm-project/clang/include/clang/AST/Expr.h index 8efa8fdbe2bb..9820bd11da86 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Expr.h +++ b/contrib/llvm-project/clang/include/clang/AST/Expr.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_AST_EXPR_H #define LLVM_CLANG_AST_EXPR_H +#include "clang/AST/APNumericStorage.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTVector.h" #include "clang/AST/ComputeDependence.h" @@ -36,6 +37,7 @@ #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/TrailingObjects.h" +#include <optional> namespace clang { class APValue; @@ -134,8 +136,8 @@ protected: void setDependence(ExprDependence Deps) { ExprBits.Dependent = static_cast<unsigned>(Deps); } - friend class ASTImporter; // Sets dependence dircetly. - friend class ASTStmtReader; // Sets dependence dircetly. + friend class ASTImporter; // Sets dependence directly. + friend class ASTStmtReader; // Sets dependence directly. public: QualType getType() const { return TR; } @@ -170,7 +172,7 @@ public: } /// Determines whether the type of this expression depends on - /// - a template paramter (C++ [temp.dep.expr], which means that its type + /// - a template parameter (C++ [temp.dep.expr], which means that its type /// could change from one template instantiation to the next) /// - or an error /// @@ -523,15 +525,25 @@ public: /// semantically correspond to a bool. bool isKnownToHaveBooleanValue(bool Semantic = true) const; + /// Check whether this array fits the idiom of a flexible array member, + /// depending on the value of -fstrict-flex-array. + /// When IgnoreTemplateOrMacroSubstitution is set, it doesn't consider sizes + /// resulting from the substitution of a macro or a template as special sizes. + bool isFlexibleArrayMemberLike( + ASTContext &Context, + LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel, + bool IgnoreTemplateOrMacroSubstitution = false) const; + /// isIntegerConstantExpr - Return the value if this expression is a valid - /// integer constant expression. If not a valid i-c-e, return None and fill - /// in Loc (if specified) with the location of the invalid expression. + /// integer constant expression. If not a valid i-c-e, return std::nullopt + /// and fill in Loc (if specified) with the location of the invalid + /// expression. /// /// Note: This does not perform the implicit conversions required by C++11 /// [expr.const]p5. - Optional<llvm::APSInt> getIntegerConstantExpr(const ASTContext &Ctx, - SourceLocation *Loc = nullptr, - bool isEvaluated = true) const; + std::optional<llvm::APSInt> + getIntegerConstantExpr(const ASTContext &Ctx, + SourceLocation *Loc = nullptr) const; bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc = nullptr) const; @@ -555,7 +567,7 @@ public: SmallVectorImpl< PartialDiagnosticAt> &Diags); - /// isPotentialConstantExprUnevaluted - Return true if this expression might + /// isPotentialConstantExprUnevaluated - Return true if this expression might /// be usable in a constant expression in C++11 in an unevaluated context, if /// it were in function FD marked constexpr. Return false if the function can /// never produce a constant expression, along with diagnostics describing @@ -572,16 +584,22 @@ public: bool isConstantInitializer(ASTContext &Ctx, bool ForRef, const Expr **Culprit = nullptr) const; + /// If this expression is an unambiguous reference to a single declaration, + /// in the style of __builtin_function_start, return that declaration. Note + /// that this may return a non-static member function or field in C++ if this + /// expression is a member pointer constant. + const ValueDecl *getAsBuiltinConstantDeclRef(const ASTContext &Context) const; + /// EvalStatus is a struct with detailed info about an evaluation in progress. struct EvalStatus { /// Whether the evaluated expression has side effects. /// For example, (f() && 0) can be folded, but it still has side effects. - bool HasSideEffects; + bool HasSideEffects = false; /// Whether the evaluation hit undefined behavior. /// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior. /// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB. - bool HasUndefinedBehavior; + bool HasUndefinedBehavior = false; /// Diag - If this is non-null, it will be filled in with a stack of notes /// indicating why evaluation failed (or why it failed to produce a constant @@ -590,10 +608,16 @@ public: /// foldable. If the expression is foldable, but not a constant expression, /// the notes will describes why it isn't a constant expression. If the /// expression *is* a constant expression, no notes will be produced. - SmallVectorImpl<PartialDiagnosticAt> *Diag; + /// + /// FIXME: this causes significant performance concerns and should be + /// refactored at some point. Not all evaluations of the constant + /// expression interpreter will display the given diagnostics, this means + /// those kinds of uses are paying the expense of generating a diagnostic + /// (which may include expensive operations like converting APValue objects + /// to a string representation). + SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr; - EvalStatus() - : HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) {} + EvalStatus() = default; // hasSideEffects - Return true if the evaluated expression has // side effects. @@ -648,8 +672,8 @@ public: SideEffectsKind AllowSideEffects = SE_NoSideEffects, bool InConstantContext = false) const; - /// EvaluateAsFloat - Return true if this is a constant which we can fold and - /// convert to a fixed point value. + /// EvaluateAsFixedPoint - Return true if this is a constant which we can fold + /// and convert to a fixed point value. bool EvaluateAsFixedPoint(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects = SE_NoSideEffects, bool InConstantContext = false) const; @@ -697,7 +721,8 @@ public: /// notes will be produced if the expression is not a constant expression. bool EvaluateAsInitializer(APValue &Result, const ASTContext &Ctx, const VarDecl *VD, - SmallVectorImpl<PartialDiagnosticAt> &Notes) const; + SmallVectorImpl<PartialDiagnosticAt> &Notes, + bool IsConstantInitializer) const; /// EvaluateWithSubstitution - Evaluate an expression as if from the context /// of a call to the given function with the given arguments, inside an @@ -739,6 +764,17 @@ public: bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, unsigned Type) const; + /// If the current Expr is a pointer, this will try to statically + /// determine the strlen of the string pointed to. + /// Returns true if all of the above holds and we were able to figure out the + /// strlen, false otherwise. + bool tryEvaluateStrLen(uint64_t &Result, ASTContext &Ctx) const; + + bool EvaluateCharRangeAsString(std::string &Result, + const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + EvalResult &Status) const; + /// Enumeration used to describe the kind of Null pointer constant /// returned from \c isNullPointerConstant(). enum NullPointerConstantKind { @@ -796,7 +832,7 @@ public: /// member expression. static QualType findBoundMemberType(const Expr *expr); - /// Skip past any invisble AST nodes which might surround this + /// Skip past any invisible AST nodes which might surround this /// statement, such as ExprWithCleanups or ImplicitCastExpr nodes, /// but also injected CXXMemberExpr and CXXConstructExpr which represent /// implicit conversions. @@ -900,7 +936,7 @@ public: return const_cast<Expr *>(this)->IgnoreParenLValueCasts(); } - /// Skip past any parenthese and casts which do not change the value + /// Skip past any parentheses and casts which do not change the value /// (including ptr->int casts of the same size) until reaching a fixed point. /// Skips: /// * What IgnoreParens() skips @@ -1014,6 +1050,9 @@ public: } }; +/// Describes the kind of result that can be tail-allocated. +enum class ConstantResultStorageKind { None, Int64, APValue }; + /// ConstantExpr - An expression that occurs in a constant context and /// optionally the result of evaluating the expression. class ConstantExpr final @@ -1026,20 +1065,15 @@ class ConstantExpr final friend class ASTStmtReader; friend class ASTStmtWriter; -public: - /// Describes the kind of result that can be tail-allocated. - enum ResultStorageKind { RSK_None, RSK_Int64, RSK_APValue }; - -private: size_t numTrailingObjects(OverloadToken<APValue>) const { - return ConstantExprBits.ResultKind == ConstantExpr::RSK_APValue; + return getResultStorageKind() == ConstantResultStorageKind::APValue; } size_t numTrailingObjects(OverloadToken<uint64_t>) const { - return ConstantExprBits.ResultKind == ConstantExpr::RSK_Int64; + return getResultStorageKind() == ConstantResultStorageKind::Int64; } uint64_t &Int64Result() { - assert(ConstantExprBits.ResultKind == ConstantExpr::RSK_Int64 && + assert(getResultStorageKind() == ConstantResultStorageKind::Int64 && "invalid accessor"); return *getTrailingObjects<uint64_t>(); } @@ -1047,7 +1081,7 @@ private: return const_cast<ConstantExpr *>(this)->Int64Result(); } APValue &APValueResult() { - assert(ConstantExprBits.ResultKind == ConstantExpr::RSK_APValue && + assert(getResultStorageKind() == ConstantResultStorageKind::APValue && "invalid accessor"); return *getTrailingObjects<APValue>(); } @@ -1055,22 +1089,23 @@ private: return const_cast<ConstantExpr *>(this)->APValueResult(); } - ConstantExpr(Expr *SubExpr, ResultStorageKind StorageKind, + ConstantExpr(Expr *SubExpr, ConstantResultStorageKind StorageKind, bool IsImmediateInvocation); - ConstantExpr(EmptyShell Empty, ResultStorageKind StorageKind); + ConstantExpr(EmptyShell Empty, ConstantResultStorageKind StorageKind); public: static ConstantExpr *Create(const ASTContext &Context, Expr *E, const APValue &Result); - static ConstantExpr *Create(const ASTContext &Context, Expr *E, - ResultStorageKind Storage = RSK_None, - bool IsImmediateInvocation = false); + static ConstantExpr * + Create(const ASTContext &Context, Expr *E, + ConstantResultStorageKind Storage = ConstantResultStorageKind::None, + bool IsImmediateInvocation = false); static ConstantExpr *CreateEmpty(const ASTContext &Context, - ResultStorageKind StorageKind); + ConstantResultStorageKind StorageKind); - static ResultStorageKind getStorageKind(const APValue &Value); - static ResultStorageKind getStorageKind(const Type *T, - const ASTContext &Context); + static ConstantResultStorageKind getStorageKind(const APValue &Value); + static ConstantResultStorageKind getStorageKind(const Type *T, + const ASTContext &Context); SourceLocation getBeginLoc() const LLVM_READONLY { return SubExpr->getBeginLoc(); @@ -1091,8 +1126,8 @@ public: APValue::ValueKind getResultAPValueKind() const { return static_cast<APValue::ValueKind>(ConstantExprBits.APValueKind); } - ResultStorageKind getResultStorageKind() const { - return static_cast<ResultStorageKind>(ConstantExprBits.ResultKind); + ConstantResultStorageKind getResultStorageKind() const { + return static_cast<ConstantResultStorageKind>(ConstantExprBits.ResultKind); } bool isImmediateInvocation() const { return ConstantExprBits.IsImmediateInvocation; @@ -1101,7 +1136,6 @@ public: return ConstantExprBits.APValueKind != APValue::None; } APValue getAPValueResult() const; - APValue &getResultAsAPValue() const { return APValueResult(); } llvm::APSInt getResultAsAPSInt() const; // Iterators child_range children() { return child_range(&SubExpr, &SubExpr+1); } @@ -1413,68 +1447,35 @@ public: return DeclRefExprBits.RefersToEnclosingVariableOrCapture; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == DeclRefExprClass; + bool isImmediateEscalating() const { + return DeclRefExprBits.IsImmediateEscalating; } - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); + void setIsImmediateEscalating(bool Set) { + DeclRefExprBits.IsImmediateEscalating = Set; } - const_child_range children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); + bool isCapturedByCopyInLambdaWithExplicitObjectParameter() const { + return DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter; } -}; -/// Used by IntegerLiteral/FloatingLiteral to store the numeric without -/// leaking memory. -/// -/// For large floats/integers, APFloat/APInt will allocate memory from the heap -/// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator -/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with -/// the APFloat/APInt values will never get freed. APNumericStorage uses -/// ASTContext's allocator for memory allocation. -class APNumericStorage { - union { - uint64_t VAL; ///< Used to store the <= 64 bits integer value. - uint64_t *pVal; ///< Used to store the >64 bits integer value. - }; - unsigned BitWidth; - - bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; } - - APNumericStorage(const APNumericStorage &) = delete; - void operator=(const APNumericStorage &) = delete; - -protected: - APNumericStorage() : VAL(0), BitWidth(0) { } - - llvm::APInt getIntValue() const { - unsigned NumWords = llvm::APInt::getNumWords(BitWidth); - if (NumWords > 1) - return llvm::APInt(BitWidth, NumWords, pVal); - else - return llvm::APInt(BitWidth, VAL); + void setCapturedByCopyInLambdaWithExplicitObjectParameter( + bool Set, const ASTContext &Context) { + DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = Set; + setDependence(computeDependence(this, Context)); } - void setIntValue(const ASTContext &C, const llvm::APInt &Val); -}; -class APIntStorage : private APNumericStorage { -public: - llvm::APInt getValue() const { return getIntValue(); } - void setValue(const ASTContext &C, const llvm::APInt &Val) { - setIntValue(C, Val); + static bool classof(const Stmt *T) { + return T->getStmtClass() == DeclRefExprClass; } -}; -class APFloatStorage : private APNumericStorage { -public: - llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const { - return llvm::APFloat(Semantics, getIntValue()); + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); } - void setValue(const ASTContext &C, const llvm::APFloat &Val) { - setIntValue(C, Val.bitcastToAPInt()); + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); } }; @@ -1568,26 +1569,18 @@ class FixedPointLiteral : public Expr, public APIntStorage { } }; -class CharacterLiteral : public Expr { -public: - enum CharacterKind { - Ascii, - Wide, - UTF8, - UTF16, - UTF32 - }; +enum class CharacterLiteralKind { Ascii, Wide, UTF8, UTF16, UTF32 }; -private: +class CharacterLiteral : public Expr { unsigned Value; SourceLocation Loc; public: // type should be IntTy - CharacterLiteral(unsigned value, CharacterKind kind, QualType type, + CharacterLiteral(unsigned value, CharacterLiteralKind kind, QualType type, SourceLocation l) : Expr(CharacterLiteralClass, type, VK_PRValue, OK_Ordinary), Value(value), Loc(l) { - CharacterLiteralBits.Kind = kind; + CharacterLiteralBits.Kind = llvm::to_underlying(kind); setDependence(ExprDependence::None); } @@ -1595,8 +1588,8 @@ public: CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { } SourceLocation getLocation() const { return Loc; } - CharacterKind getKind() const { - return static_cast<CharacterKind>(CharacterLiteralBits.Kind); + CharacterLiteralKind getKind() const { + return static_cast<CharacterLiteralKind>(CharacterLiteralBits.Kind); } SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } @@ -1605,14 +1598,16 @@ public: unsigned getValue() const { return Value; } void setLocation(SourceLocation Location) { Loc = Location; } - void setKind(CharacterKind kind) { CharacterLiteralBits.Kind = kind; } + void setKind(CharacterLiteralKind kind) { + CharacterLiteralBits.Kind = llvm::to_underlying(kind); + } void setValue(unsigned Val) { Value = Val; } static bool classof(const Stmt *T) { return T->getStmtClass() == CharacterLiteralClass; } - static void print(unsigned val, CharacterKind Kind, raw_ostream &OS); + static void print(unsigned val, CharacterLiteralKind Kind, raw_ostream &OS); // Iterators child_range children() { @@ -1734,6 +1729,15 @@ public: } }; +enum class StringLiteralKind { + Ordinary, + Wide, + UTF8, + UTF16, + UTF32, + Unevaluated +}; + /// StringLiteral - This represents a string literal expression, e.g. "foo" /// or L"bar" (wide strings). The actual string data can be obtained with /// getBytes() and is NOT null-terminated. The length of the string data is @@ -1772,10 +1776,6 @@ class StringLiteral final /// /// * An array of getByteLength() char used to store the string data. -public: - enum StringKind { Ascii, Wide, UTF8, UTF16, UTF32 }; - -private: unsigned numTrailingObjects(OverloadToken<unsigned>) const { return 1; } unsigned numTrailingObjects(OverloadToken<SourceLocation>) const { return getNumConcatenated(); @@ -1797,7 +1797,7 @@ private: } /// Build a string literal. - StringLiteral(const ASTContext &Ctx, StringRef Str, StringKind Kind, + StringLiteral(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumConcatenated); @@ -1806,7 +1806,8 @@ private: unsigned CharByteWidth); /// Map a target and string kind to the appropriate character width. - static unsigned mapCharByteWidth(TargetInfo const &Target, StringKind SK); + static unsigned mapCharByteWidth(TargetInfo const &Target, + StringLiteralKind SK); /// Set one of the string literal token. void setStrTokenLoc(unsigned TokNum, SourceLocation L) { @@ -1818,13 +1819,13 @@ public: /// This is the "fully general" constructor that allows representation of /// strings formed from multiple concatenated tokens. static StringLiteral *Create(const ASTContext &Ctx, StringRef Str, - StringKind Kind, bool Pascal, QualType Ty, + StringLiteralKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumConcatenated); /// Simple constructor for string literals made from one token. static StringLiteral *Create(const ASTContext &Ctx, StringRef Str, - StringKind Kind, bool Pascal, QualType Ty, + StringLiteralKind Kind, bool Pascal, QualType Ty, SourceLocation Loc) { return Create(Ctx, Str, Kind, Pascal, Ty, &Loc, 1); } @@ -1835,7 +1836,7 @@ public: unsigned CharByteWidth); StringRef getString() const { - assert(getCharByteWidth() == 1 && + assert((isUnevaluated() || getCharByteWidth() == 1) && "This function is used in places that assume strings use char"); return StringRef(getStrDataAsChar(), getByteLength()); } @@ -1866,15 +1867,16 @@ public: unsigned getLength() const { return *getTrailingObjects<unsigned>(); } unsigned getCharByteWidth() const { return StringLiteralBits.CharByteWidth; } - StringKind getKind() const { - return static_cast<StringKind>(StringLiteralBits.Kind); + StringLiteralKind getKind() const { + return static_cast<StringLiteralKind>(StringLiteralBits.Kind); } - bool isAscii() const { return getKind() == Ascii; } - bool isWide() const { return getKind() == Wide; } - bool isUTF8() const { return getKind() == UTF8; } - bool isUTF16() const { return getKind() == UTF16; } - bool isUTF32() const { return getKind() == UTF32; } + bool isOrdinary() const { return getKind() == StringLiteralKind::Ordinary; } + bool isWide() const { return getKind() == StringLiteralKind::Wide; } + bool isUTF8() const { return getKind() == StringLiteralKind::UTF8; } + bool isUTF16() const { return getKind() == StringLiteralKind::UTF16; } + bool isUTF32() const { return getKind() == StringLiteralKind::UTF32; } + bool isUnevaluated() const { return getKind() == StringLiteralKind::Unevaluated; } bool isPascal() const { return StringLiteralBits.IsPascal; } bool containsNonAscii() const { @@ -1942,6 +1944,19 @@ public: } }; +enum class PredefinedIdentKind { + Func, + Function, + LFunction, // Same as Function, but as wide string. + FuncDName, + FuncSig, + LFuncSig, // Same as FuncSig, but as wide string + PrettyFunction, + /// The same as PrettyFunction, except that the + /// 'virtual' keyword is omitted for virtual member functions. + PrettyFunctionNoVirtual +}; + /// [C99 6.4.2.2] - A predefined identifier such as __func__. class PredefinedExpr final : public Expr, @@ -1953,23 +1968,8 @@ class PredefinedExpr final // "Stmt *" for the predefined identifier. It is present if and only if // hasFunctionName() is true and is always a "StringLiteral *". -public: - enum IdentKind { - Func, - Function, - LFunction, // Same as Function, but as wide string. - FuncDName, - FuncSig, - LFuncSig, // Same as FuncSig, but as as wide string - PrettyFunction, - /// The same as PrettyFunction, except that the - /// 'virtual' keyword is omitted for virtual member functions. - PrettyFunctionNoVirtual - }; - -private: - PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK, - StringLiteral *SL); + PredefinedExpr(SourceLocation L, QualType FNTy, PredefinedIdentKind IK, + bool IsTransparent, StringLiteral *SL); explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName); @@ -1984,17 +1984,23 @@ private: public: /// Create a PredefinedExpr. + /// + /// If IsTransparent, the PredefinedExpr is transparently handled as a + /// StringLiteral. static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L, - QualType FNTy, IdentKind IK, StringLiteral *SL); + QualType FNTy, PredefinedIdentKind IK, + bool IsTransparent, StringLiteral *SL); /// Create an empty PredefinedExpr. static PredefinedExpr *CreateEmpty(const ASTContext &Ctx, bool HasFunctionName); - IdentKind getIdentKind() const { - return static_cast<IdentKind>(PredefinedExprBits.Kind); + PredefinedIdentKind getIdentKind() const { + return static_cast<PredefinedIdentKind>(PredefinedExprBits.Kind); } + bool isTransparent() const { return PredefinedExprBits.IsTransparent; } + SourceLocation getLocation() const { return PredefinedExprBits.Loc; } void setLocation(SourceLocation L) { PredefinedExprBits.Loc = L; } @@ -2010,12 +2016,13 @@ public: : nullptr; } - static StringRef getIdentKindName(IdentKind IK); + static StringRef getIdentKindName(PredefinedIdentKind IK); StringRef getIdentKindName() const { return getIdentKindName(getIdentKind()); } - static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl); + static std::string ComputeName(PredefinedIdentKind IK, + const Decl *CurrentDecl); SourceLocation getBeginLoc() const { return getLocation(); } SourceLocation getEndLoc() const { return getLocation(); } @@ -2210,14 +2217,14 @@ public: bool canOverflow() const { return UnaryOperatorBits.CanOverflow; } void setCanOverflow(bool C) { UnaryOperatorBits.CanOverflow = C; } - // Get the FP contractability status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FP contractability status of this operator. Only meaningful for + /// operations on floating point types. bool isFPContractableWithinStatement(const LangOptions &LO) const { return getFPFeaturesInEffect(LO).allowFPContractWithinStatement(); } - // Get the FENV_ACCESS status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FENV_ACCESS status of this operator. Only meaningful for + /// operations on floating point types. bool isFEnvAccessOn(const LangOptions &LO) const { return getFPFeaturesInEffect(LO).getAllowFEnvAccess(); } @@ -2298,12 +2305,12 @@ public: } protected: - /// Set FPFeatures in trailing storage, used only by Serialization + /// Set FPFeatures in trailing storage, used by Serialization & ASTImporter. void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; } public: - // Get the FP features status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FP features status of this operator. Only meaningful for + /// operations on floating point types. FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { if (UnaryOperatorBits.HasFPFeatures) return getStoredFPFeatures().applyOverrides(LO); @@ -2316,6 +2323,7 @@ public: } friend TrailingObjects; + friend class ASTNodeImporter; friend class ASTReader; friend class ASTStmtReader; friend class ASTStmtWriter; @@ -2375,7 +2383,7 @@ public: /// Create an offsetof node that refers into a C++ base class. explicit OffsetOfNode(const CXXBaseSpecifier *Base) - : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {} + : Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {} /// Determine what kind of offsetof node this is. Kind getKind() const { return static_cast<Kind>(Data & Mask); } @@ -2791,7 +2799,7 @@ class CallExpr : public Expr { /// The number of arguments in the call expression. unsigned NumArgs; - /// The location of the right parenthese. This has a different meaning for + /// The location of the right parentheses. This has a different meaning for /// the derived classes of CallExpr. SourceLocation RParenLoc; @@ -2997,7 +3005,7 @@ public: /// Compute and set dependence bits. void computeDependence() { setDependence(clang::computeDependence( - this, llvm::makeArrayRef( + this, llvm::ArrayRef( reinterpret_cast<Expr **>(getTrailingStmts() + PREARGS_START), getNumPreArgs()))); } @@ -3044,14 +3052,10 @@ public: /// interface. This provides efficient reverse iteration of the /// subexpressions. This is currently used for CFG construction. ArrayRef<Stmt *> getRawSubExprs() { - return llvm::makeArrayRef(getTrailingStmts(), - PREARGS_START + getNumPreArgs() + getNumArgs()); + return llvm::ArrayRef(getTrailingStmts(), + PREARGS_START + getNumPreArgs() + getNumArgs()); } - /// getNumCommas - Return the number of commas that must have been present in - /// this function call. - unsigned getNumCommas() const { return getNumArgs() ? getNumArgs() - 1 : 0; } - /// Get FPOptionsOverride from trailing storage. FPOptionsOverride getStoredFPFeatures() const { assert(hasStoredFPFeatures()); @@ -3063,8 +3067,8 @@ public: *getTrailingFPFeatures() = F; } - // Get the FP features status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FP features status of this operator. Only meaningful for + /// operations on floating point types. FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { if (hasStoredFPFeatures()) return getStoredFPFeatures().applyOverrides(LO); @@ -3115,11 +3119,7 @@ public: setDependence(getDependence() | ExprDependence::TypeValueInstantiation); } - bool isCallToStdMove() const { - const FunctionDecl *FD = getDirectCallee(); - return getNumArgs() == 1 && FD && FD->isInStdNamespace() && - FD->getIdentifier() && FD->getIdentifier()->isStr("move"); - } + bool isCallToStdMove() const; static bool classof(const Stmt *T) { return T->getStmtClass() >= firstCallExprConstant && @@ -3484,7 +3484,6 @@ protected: CastExprBits.BasePathSize = BasePathSize; assert((CastExprBits.BasePathSize == BasePathSize) && "BasePathSize overflow!"); - setDependence(computeDependence(this)); assert(CastConsistency()); CastExprBits.HasFPFeatures = HasFPFeatures; } @@ -3559,8 +3558,8 @@ public: return *getTrailingFPFeatures(); } - // Get the FP features status of this operation. Only meaningful for - // operations on floating point types. + /// Get the FP features status of this operation. Only meaningful for + /// operations on floating point types. FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { if (hasStoredFPFeatures()) return getStoredFPFeatures().applyOverrides(LO); @@ -3573,6 +3572,19 @@ public: return FPOptionsOverride(); } + /// Return + // True : if this conversion changes the volatile-ness of a gl-value. + // Qualification conversions on gl-values currently use CK_NoOp, but + // it's important to recognize volatile-changing conversions in + // clients code generation that normally eagerly peephole loads. Note + // that the query is answering for this specific node; Sema may + // produce multiple cast nodes for any particular conversion sequence. + // False : Otherwise. + bool changesVolatileQualification() const { + return (isGLValue() && (getType().isVolatileQualified() != + getSubExpr()->getType().isVolatileQualified())); + } + static const FieldDecl *getTargetFieldForToUnionCast(QualType unionType, QualType opType); static const FieldDecl *getTargetFieldForToUnionCast(const RecordDecl *RD, @@ -3618,6 +3630,7 @@ class ImplicitCastExpr final ExprValueKind VK) : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength, FPO.requiresTrailingStorage()) { + setDependence(computeDependence(this)); if (hasStoredFPFeatures()) *getTrailingFPFeatures() = FPO; } @@ -3695,7 +3708,9 @@ protected: CastKind kind, Expr *op, unsigned PathSize, bool HasFPFeatures, TypeSourceInfo *writtenTy) : CastExpr(SC, exprTy, VK, kind, op, PathSize, HasFPFeatures), - TInfo(writtenTy) {} + TInfo(writtenTy) { + setDependence(computeDependence(this)); + } /// Construct an empty explicit cast. ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize, @@ -3954,11 +3969,12 @@ public: return isShiftAssignOp(getOpcode()); } - // Return true if a binary operator using the specified opcode and operands - // would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized - // integer to a pointer. + /// Return true if a binary operator using the specified opcode and operands + /// would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized + /// integer to a pointer. static bool isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc, - Expr *LHS, Expr *RHS); + const Expr *LHS, + const Expr *RHS); static bool classof(const Stmt *S) { return S->getStmtClass() >= firstBinaryOperatorConstant && @@ -3989,8 +4005,8 @@ public: *getTrailingFPFeatures() = F; } - // Get the FP features status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FP features status of this operator. Only meaningful for + /// operations on floating point types. FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { if (BinaryOperatorBits.HasFPFeatures) return getStoredFPFeatures().applyOverrides(LO); @@ -3998,20 +4014,20 @@ public: } // This is used in ASTImporter - FPOptionsOverride getFPFeatures(const LangOptions &LO) const { + FPOptionsOverride getFPFeatures() const { if (BinaryOperatorBits.HasFPFeatures) return getStoredFPFeatures(); return FPOptionsOverride(); } - // Get the FP contractability status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FP contractability status of this operator. Only meaningful for + /// operations on floating point types. bool isFPContractableWithinStatement(const LangOptions &LO) const { return getFPFeaturesInEffect(LO).allowFPContractWithinStatement(); } - // Get the FENV_ACCESS status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FENV_ACCESS status of this operator. Only meaningful for + /// operations on floating point types. bool isFEnvAccessOn(const LangOptions &LO) const { return getFPFeaturesInEffect(LO).getAllowFEnvAccess(); } @@ -4107,17 +4123,17 @@ protected: : Expr(SC, Empty) { } public: - // getCond - Return the expression representing the condition for - // the ?: operator. + /// getCond - Return the expression representing the condition for + /// the ?: operator. Expr *getCond() const; - // getTrueExpr - Return the subexpression representing the value of - // the expression if the condition evaluates to true. + /// getTrueExpr - Return the subexpression representing the value of + /// the expression if the condition evaluates to true. Expr *getTrueExpr() const; - // getFalseExpr - Return the subexpression representing the value of - // the expression if the condition evaluates to false. This is - // the same as getRHS. + /// getFalseExpr - Return the subexpression representing the value of + /// the expression if the condition evaluates to false. This is + /// the same as getRHS. Expr *getFalseExpr() const; SourceLocation getQuestionLoc() const { return QuestionLoc; } @@ -4152,17 +4168,17 @@ public: explicit ConditionalOperator(EmptyShell Empty) : AbstractConditionalOperator(ConditionalOperatorClass, Empty) { } - // getCond - Return the expression representing the condition for - // the ?: operator. + /// getCond - Return the expression representing the condition for + /// the ?: operator. Expr *getCond() const { return cast<Expr>(SubExprs[COND]); } - // getTrueExpr - Return the subexpression representing the value of - // the expression if the condition evaluates to true. + /// getTrueExpr - Return the subexpression representing the value of + /// the expression if the condition evaluates to true. Expr *getTrueExpr() const { return cast<Expr>(SubExprs[LHS]); } - // getFalseExpr - Return the subexpression representing the value of - // the expression if the condition evaluates to false. This is - // the same as getRHS. + /// getFalseExpr - Return the subexpression representing the value of + /// the expression if the condition evaluates to false. This is + /// the same as getRHS. Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); } Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } @@ -4666,16 +4682,26 @@ public: } }; +enum class SourceLocIdentKind { + Function, + FuncSig, + File, + FileName, + Line, + Column, + SourceLocStruct +}; + /// Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(), -/// __builtin_FUNCTION(), or __builtin_FILE(). +/// __builtin_FUNCTION(), __builtin_FUNCSIG(), __builtin_FILE(), +/// __builtin_FILE_NAME() or __builtin_source_location(). class SourceLocExpr final : public Expr { SourceLocation BuiltinLoc, RParenLoc; DeclContext *ParentContext; public: - enum IdentKind { Function, File, Line, Column }; - - SourceLocExpr(const ASTContext &Ctx, IdentKind Type, SourceLocation BLoc, + SourceLocExpr(const ASTContext &Ctx, SourceLocIdentKind Type, + QualType ResultTy, SourceLocation BLoc, SourceLocation RParenLoc, DeclContext *Context); /// Build an empty call expression. @@ -4689,22 +4715,24 @@ public: /// Return a string representing the name of the specific builtin function. StringRef getBuiltinStr() const; - IdentKind getIdentKind() const { - return static_cast<IdentKind>(SourceLocExprBits.Kind); + SourceLocIdentKind getIdentKind() const { + return static_cast<SourceLocIdentKind>(SourceLocExprBits.Kind); } - bool isStringType() const { + bool isIntType() const { switch (getIdentKind()) { - case File: - case Function: - return true; - case Line: - case Column: + case SourceLocIdentKind::File: + case SourceLocIdentKind::FileName: + case SourceLocIdentKind::Function: + case SourceLocIdentKind::FuncSig: + case SourceLocIdentKind::SourceLocStruct: return false; + case SourceLocIdentKind::Line: + case SourceLocIdentKind::Column: + return true; } llvm_unreachable("unknown source location expression kind"); } - bool isIntType() const LLVM_READONLY { return !isStringType(); } /// If the SourceLocExpr has been resolved return the subexpression /// representing the resolved value. Otherwise return null. @@ -4727,6 +4755,17 @@ public: return T->getStmtClass() == SourceLocExprClass; } + static bool MayBeDependent(SourceLocIdentKind Kind) { + switch (Kind) { + case SourceLocIdentKind::Function: + case SourceLocIdentKind::FuncSig: + case SourceLocIdentKind::SourceLocStruct: + return true; + default: + return false; + } + } + private: friend class ASTStmtReader; }; @@ -4816,12 +4855,10 @@ public: return reinterpret_cast<Expr * const *>(InitExprs.data()); } - ArrayRef<Expr *> inits() { - return llvm::makeArrayRef(getInits(), getNumInits()); - } + ArrayRef<Expr *> inits() { return llvm::ArrayRef(getInits(), getNumInits()); } ArrayRef<Expr *> inits() const { - return llvm::makeArrayRef(getInits(), getNumInits()); + return llvm::ArrayRef(getInits(), getNumInits()); } const Expr *getInit(unsigned Init) const { @@ -4884,6 +4921,13 @@ public: /// has been set. bool hasArrayFiller() const { return getArrayFiller(); } + /// Determine whether this initializer list contains a designated initializer. + bool hasDesignatedInit() const { + return std::any_of(begin(), end(), [](const Stmt *S) { + return isa<DesignatedInitExpr>(S); + }); + } + /// If this initializes a union, specifies which field in the /// union to initialize. /// @@ -4912,8 +4956,8 @@ public: return LBraceLoc.isValid() && RBraceLoc.isValid(); } - // Is this an initializer for an array of characters, initialized by a string - // literal or an @encode? + /// Is this an initializer for an array of characters, initialized by a string + /// literal or an @encode? bool isStringLiteralInit() const; /// Is this a transparent initializer list (that is, an InitListExpr that is @@ -5028,6 +5072,7 @@ private: /// Whether this designated initializer used the GNU deprecated /// syntax rather than the C99 '=' syntax. + LLVM_PREFERRED_TYPE(bool) unsigned GNUSyntax : 1; /// The number of designators in this initializer expression. @@ -5052,37 +5097,6 @@ private: NumDesignators(0), NumSubExprs(NumSubExprs), Designators(nullptr) { } public: - /// A field designator, e.g., ".x". - struct FieldDesignator { - /// Refers to the field that is being initialized. The low bit - /// of this field determines whether this is actually a pointer - /// to an IdentifierInfo (if 1) or a FieldDecl (if 0). When - /// initially constructed, a field designator will store an - /// IdentifierInfo*. After semantic analysis has resolved that - /// name, the field designator will instead store a FieldDecl*. - uintptr_t NameOrField; - - /// The location of the '.' in the designated initializer. - SourceLocation DotLoc; - - /// The location of the field name in the designated initializer. - SourceLocation FieldLoc; - }; - - /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". - struct ArrayOrRangeDesignator { - /// Location of the first index expression within the designated - /// initializer expression's list of subexpressions. - unsigned Index; - /// The location of the '[' starting the array range designator. - SourceLocation LBracketLoc; - /// The location of the ellipsis separating the start and end - /// indices. Only valid for GNU array-range designators. - SourceLocation EllipsisLoc; - /// The location of the ']' terminating the array range designator. - SourceLocation RBracketLoc; - }; - /// Represents a single C99 designator. /// /// @todo This class is infuriatingly similar to clang::Designator, @@ -5090,118 +5104,177 @@ public: /// keep us from reusing it. Try harder, later, to rectify these /// differences. class Designator { + /// A field designator, e.g., ".x". + struct FieldDesignatorInfo { + /// Refers to the field that is being initialized. The low bit + /// of this field determines whether this is actually a pointer + /// to an IdentifierInfo (if 1) or a FieldDecl (if 0). When + /// initially constructed, a field designator will store an + /// IdentifierInfo*. After semantic analysis has resolved that + /// name, the field designator will instead store a FieldDecl*. + uintptr_t NameOrField; + + /// The location of the '.' in the designated initializer. + SourceLocation DotLoc; + + /// The location of the field name in the designated initializer. + SourceLocation FieldLoc; + + FieldDesignatorInfo(const IdentifierInfo *II, SourceLocation DotLoc, + SourceLocation FieldLoc) + : NameOrField(reinterpret_cast<uintptr_t>(II) | 0x1), DotLoc(DotLoc), + FieldLoc(FieldLoc) {} + }; + + /// An array or GNU array-range designator, e.g., "[9]" or "[10...15]". + struct ArrayOrRangeDesignatorInfo { + /// Location of the first index expression within the designated + /// initializer expression's list of subexpressions. + unsigned Index; + + /// The location of the '[' starting the array range designator. + SourceLocation LBracketLoc; + + /// The location of the ellipsis separating the start and end + /// indices. Only valid for GNU array-range designators. + SourceLocation EllipsisLoc; + + /// The location of the ']' terminating the array range designator. + SourceLocation RBracketLoc; + + ArrayOrRangeDesignatorInfo(unsigned Index, SourceLocation LBracketLoc, + SourceLocation RBracketLoc) + : Index(Index), LBracketLoc(LBracketLoc), RBracketLoc(RBracketLoc) {} + + ArrayOrRangeDesignatorInfo(unsigned Index, + SourceLocation LBracketLoc, + SourceLocation EllipsisLoc, + SourceLocation RBracketLoc) + : Index(Index), LBracketLoc(LBracketLoc), EllipsisLoc(EllipsisLoc), + RBracketLoc(RBracketLoc) {} + }; + /// The kind of designator this describes. - enum { + enum DesignatorKind { FieldDesignator, ArrayDesignator, ArrayRangeDesignator - } Kind; + }; + + DesignatorKind Kind; union { /// A field designator, e.g., ".x". - struct FieldDesignator Field; + struct FieldDesignatorInfo FieldInfo; + /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". - struct ArrayOrRangeDesignator ArrayOrRange; + struct ArrayOrRangeDesignatorInfo ArrayOrRangeInfo; }; - friend class DesignatedInitExpr; + + Designator(DesignatorKind Kind) : Kind(Kind) {} public: Designator() {} - /// Initializes a field designator. - Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc, - SourceLocation FieldLoc) - : Kind(FieldDesignator) { - new (&Field) DesignatedInitExpr::FieldDesignator; - Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01; - Field.DotLoc = DotLoc; - Field.FieldLoc = FieldLoc; - } - - /// Initializes an array designator. - Designator(unsigned Index, SourceLocation LBracketLoc, - SourceLocation RBracketLoc) - : Kind(ArrayDesignator) { - new (&ArrayOrRange) DesignatedInitExpr::ArrayOrRangeDesignator; - ArrayOrRange.Index = Index; - ArrayOrRange.LBracketLoc = LBracketLoc; - ArrayOrRange.EllipsisLoc = SourceLocation(); - ArrayOrRange.RBracketLoc = RBracketLoc; - } - - /// Initializes a GNU array-range designator. - Designator(unsigned Index, SourceLocation LBracketLoc, - SourceLocation EllipsisLoc, SourceLocation RBracketLoc) - : Kind(ArrayRangeDesignator) { - new (&ArrayOrRange) DesignatedInitExpr::ArrayOrRangeDesignator; - ArrayOrRange.Index = Index; - ArrayOrRange.LBracketLoc = LBracketLoc; - ArrayOrRange.EllipsisLoc = EllipsisLoc; - ArrayOrRange.RBracketLoc = RBracketLoc; - } - bool isFieldDesignator() const { return Kind == FieldDesignator; } bool isArrayDesignator() const { return Kind == ArrayDesignator; } bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; } - IdentifierInfo *getFieldName() const; + //===------------------------------------------------------------------===// + // FieldDesignatorInfo + + /// Creates a field designator. + static Designator CreateFieldDesignator(const IdentifierInfo *FieldName, + SourceLocation DotLoc, + SourceLocation FieldLoc) { + Designator D(FieldDesignator); + new (&D.FieldInfo) FieldDesignatorInfo(FieldName, DotLoc, FieldLoc); + return D; + } - FieldDecl *getField() const { - assert(Kind == FieldDesignator && "Only valid on a field designator"); - if (Field.NameOrField & 0x01) + const IdentifierInfo *getFieldName() const; + + FieldDecl *getFieldDecl() const { + assert(isFieldDesignator() && "Only valid on a field designator"); + if (FieldInfo.NameOrField & 0x01) return nullptr; - else - return reinterpret_cast<FieldDecl *>(Field.NameOrField); + return reinterpret_cast<FieldDecl *>(FieldInfo.NameOrField); } - void setField(FieldDecl *FD) { - assert(Kind == FieldDesignator && "Only valid on a field designator"); - Field.NameOrField = reinterpret_cast<uintptr_t>(FD); + void setFieldDecl(FieldDecl *FD) { + assert(isFieldDesignator() && "Only valid on a field designator"); + FieldInfo.NameOrField = reinterpret_cast<uintptr_t>(FD); } SourceLocation getDotLoc() const { - assert(Kind == FieldDesignator && "Only valid on a field designator"); - return Field.DotLoc; + assert(isFieldDesignator() && "Only valid on a field designator"); + return FieldInfo.DotLoc; } SourceLocation getFieldLoc() const { - assert(Kind == FieldDesignator && "Only valid on a field designator"); - return Field.FieldLoc; + assert(isFieldDesignator() && "Only valid on a field designator"); + return FieldInfo.FieldLoc; } - SourceLocation getLBracketLoc() const { - assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && + //===------------------------------------------------------------------===// + // ArrayOrRangeDesignator + + /// Creates an array designator. + static Designator CreateArrayDesignator(unsigned Index, + SourceLocation LBracketLoc, + SourceLocation RBracketLoc) { + Designator D(ArrayDesignator); + new (&D.ArrayOrRangeInfo) ArrayOrRangeDesignatorInfo(Index, LBracketLoc, + RBracketLoc); + return D; + } + + /// Creates a GNU array-range designator. + static Designator CreateArrayRangeDesignator(unsigned Index, + SourceLocation LBracketLoc, + SourceLocation EllipsisLoc, + SourceLocation RBracketLoc) { + Designator D(ArrayRangeDesignator); + new (&D.ArrayOrRangeInfo) ArrayOrRangeDesignatorInfo(Index, LBracketLoc, + EllipsisLoc, + RBracketLoc); + return D; + } + + unsigned getArrayIndex() const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && "Only valid on an array or array-range designator"); - return ArrayOrRange.LBracketLoc; + return ArrayOrRangeInfo.Index; } - SourceLocation getRBracketLoc() const { - assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && + SourceLocation getLBracketLoc() const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && "Only valid on an array or array-range designator"); - return ArrayOrRange.RBracketLoc; + return ArrayOrRangeInfo.LBracketLoc; } SourceLocation getEllipsisLoc() const { - assert(Kind == ArrayRangeDesignator && + assert(isArrayRangeDesignator() && "Only valid on an array-range designator"); - return ArrayOrRange.EllipsisLoc; + return ArrayOrRangeInfo.EllipsisLoc; } - unsigned getFirstExprIndex() const { - assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && + SourceLocation getRBracketLoc() const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && "Only valid on an array or array-range designator"); - return ArrayOrRange.Index; + return ArrayOrRangeInfo.RBracketLoc; } SourceLocation getBeginLoc() const LLVM_READONLY { - if (Kind == FieldDesignator) - return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc(); - else - return getLBracketLoc(); + if (isFieldDesignator()) + return getDotLoc().isInvalid() ? getFieldLoc() : getDotLoc(); + return getLBracketLoc(); } + SourceLocation getEndLoc() const LLVM_READONLY { - return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc(); + return isFieldDesignator() ? getFieldLoc() : getRBracketLoc(); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getBeginLoc(), getEndLoc()); } @@ -5563,9 +5636,7 @@ public: return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>()); } - ArrayRef<Expr *> exprs() { - return llvm::makeArrayRef(getExprs(), getNumExprs()); - } + ArrayRef<Expr *> exprs() { return llvm::ArrayRef(getExprs(), getNumExprs()); } SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } @@ -5613,6 +5684,12 @@ public: /// which names a dependent type in its association list is result-dependent, /// which means that the choice of result expression is dependent. /// Result-dependent generic associations are both type- and value-dependent. +/// +/// We also allow an extended form in both C and C++ where the controlling +/// predicate for the selection expression is a type rather than an expression. +/// This type argument form does not perform any conversions for the +/// controlling type, which makes it suitable for use with qualified type +/// associations, which is not possible with the expression form. class GenericSelectionExpr final : public Expr, private llvm::TrailingObjects<GenericSelectionExpr, Stmt *, @@ -5625,31 +5702,68 @@ class GenericSelectionExpr final /// expression in the case where the generic selection expression is not /// result-dependent. The result index is equal to ResultDependentIndex /// if and only if the generic selection expression is result-dependent. - unsigned NumAssocs, ResultIndex; + unsigned NumAssocs : 15; + unsigned ResultIndex : 15; // NB: ResultDependentIndex is tied to this width. + LLVM_PREFERRED_TYPE(bool) + unsigned IsExprPredicate : 1; enum : unsigned { - ResultDependentIndex = std::numeric_limits<unsigned>::max(), - ControllingIndex = 0, - AssocExprStartIndex = 1 + ResultDependentIndex = 0x7FFF }; + unsigned getIndexOfControllingExpression() const { + // If controlled by an expression, the first offset into the Stmt * + // trailing array is the controlling expression, the associated expressions + // follow this. + assert(isExprPredicate() && "Asking for the controlling expression of a " + "selection expr predicated by a type"); + return 0; + } + + unsigned getIndexOfControllingType() const { + // If controlled by a type, the first offset into the TypeSourceInfo * + // trailing array is the controlling type, the associated types follow this. + assert(isTypePredicate() && "Asking for the controlling type of a " + "selection expr predicated by an expression"); + return 0; + } + + unsigned getIndexOfStartOfAssociatedExprs() const { + // If the predicate is a type, then the associated expressions are the only + // Stmt * in the trailing array, otherwise we need to offset past the + // predicate expression. + return (int)isExprPredicate(); + } + + unsigned getIndexOfStartOfAssociatedTypes() const { + // If the predicate is a type, then the associated types follow it in the + // trailing array. Otherwise, the associated types are the only + // TypeSourceInfo * in the trailing array. + return (int)isTypePredicate(); + } + + /// The location of the "default" and of the right parenthesis. SourceLocation DefaultLoc, RParenLoc; // GenericSelectionExpr is followed by several trailing objects. // They are (in order): // - // * A single Stmt * for the controlling expression. + // * A single Stmt * for the controlling expression or a TypeSourceInfo * for + // the controlling type, depending on the result of isTypePredicate() or + // isExprPredicate(). // * An array of getNumAssocs() Stmt * for the association expressions. // * An array of getNumAssocs() TypeSourceInfo *, one for each of the // association expressions. unsigned numTrailingObjects(OverloadToken<Stmt *>) const { // Add one to account for the controlling expression; the remainder // are the associated expressions. - return 1 + getNumAssocs(); + return getNumAssocs() + (int)isExprPredicate(); } unsigned numTrailingObjects(OverloadToken<TypeSourceInfo *>) const { - return getNumAssocs(); + // Add one to account for the controlling type predicate, the remainder + // are the associated types. + return getNumAssocs() + (int)isTypePredicate(); } template <bool Const> class AssociationIteratorTy; @@ -5730,7 +5844,8 @@ class GenericSelectionExpr final bool operator==(AssociationIteratorTy Other) const { return E == Other.E; } }; // class AssociationIterator - /// Build a non-result-dependent generic selection expression. + /// Build a non-result-dependent generic selection expression accepting an + /// expression predicate. GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef<TypeSourceInfo *> AssocTypes, @@ -5739,7 +5854,8 @@ class GenericSelectionExpr final bool ContainsUnexpandedParameterPack, unsigned ResultIndex); - /// Build a result-dependent generic selection expression. + /// Build a result-dependent generic selection expression accepting an + /// expression predicate. GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef<TypeSourceInfo *> AssocTypes, @@ -5747,11 +5863,31 @@ class GenericSelectionExpr final SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack); + /// Build a non-result-dependent generic selection expression accepting a + /// type predicate. + GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, + TypeSourceInfo *ControllingType, + ArrayRef<TypeSourceInfo *> AssocTypes, + ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack, + unsigned ResultIndex); + + /// Build a result-dependent generic selection expression accepting a type + /// predicate. + GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, + TypeSourceInfo *ControllingType, + ArrayRef<TypeSourceInfo *> AssocTypes, + ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack); + /// Build an empty generic selection expression for deserialization. explicit GenericSelectionExpr(EmptyShell Empty, unsigned NumAssocs); public: - /// Create a non-result-dependent generic selection expression. + /// Create a non-result-dependent generic selection expression accepting an + /// expression predicate. static GenericSelectionExpr * Create(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef<TypeSourceInfo *> AssocTypes, @@ -5759,13 +5895,31 @@ public: SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack, unsigned ResultIndex); - /// Create a result-dependent generic selection expression. + /// Create a result-dependent generic selection expression accepting an + /// expression predicate. static GenericSelectionExpr * Create(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef<TypeSourceInfo *> AssocTypes, ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc, SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack); + /// Create a non-result-dependent generic selection expression accepting a + /// type predicate. + static GenericSelectionExpr * + Create(const ASTContext &Context, SourceLocation GenericLoc, + TypeSourceInfo *ControllingType, ArrayRef<TypeSourceInfo *> AssocTypes, + ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack, + unsigned ResultIndex); + + /// Create a result-dependent generic selection expression accepting a type + /// predicate + static GenericSelectionExpr * + Create(const ASTContext &Context, SourceLocation GenericLoc, + TypeSourceInfo *ControllingType, ArrayRef<TypeSourceInfo *> AssocTypes, + ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack); + /// Create an empty generic selection expression for deserialization. static GenericSelectionExpr *CreateEmpty(const ASTContext &Context, unsigned NumAssocs); @@ -5793,32 +5947,56 @@ public: /// Whether this generic selection is result-dependent. bool isResultDependent() const { return ResultIndex == ResultDependentIndex; } + /// Whether this generic selection uses an expression as its controlling + /// argument. + bool isExprPredicate() const { return IsExprPredicate; } + /// Whether this generic selection uses a type as its controlling argument. + bool isTypePredicate() const { return !IsExprPredicate; } + /// Return the controlling expression of this generic selection expression. + /// Only valid to call if the selection expression used an expression as its + /// controlling argument. Expr *getControllingExpr() { - return cast<Expr>(getTrailingObjects<Stmt *>()[ControllingIndex]); + return cast<Expr>( + getTrailingObjects<Stmt *>()[getIndexOfControllingExpression()]); } const Expr *getControllingExpr() const { - return cast<Expr>(getTrailingObjects<Stmt *>()[ControllingIndex]); + return cast<Expr>( + getTrailingObjects<Stmt *>()[getIndexOfControllingExpression()]); + } + + /// Return the controlling type of this generic selection expression. Only + /// valid to call if the selection expression used a type as its controlling + /// argument. + TypeSourceInfo *getControllingType() { + return getTrailingObjects<TypeSourceInfo *>()[getIndexOfControllingType()]; + } + const TypeSourceInfo* getControllingType() const { + return getTrailingObjects<TypeSourceInfo *>()[getIndexOfControllingType()]; } /// Return the result expression of this controlling expression. Defined if /// and only if the generic selection expression is not result-dependent. Expr *getResultExpr() { return cast<Expr>( - getTrailingObjects<Stmt *>()[AssocExprStartIndex + getResultIndex()]); + getTrailingObjects<Stmt *>()[getIndexOfStartOfAssociatedExprs() + + getResultIndex()]); } const Expr *getResultExpr() const { return cast<Expr>( - getTrailingObjects<Stmt *>()[AssocExprStartIndex + getResultIndex()]); + getTrailingObjects<Stmt *>()[getIndexOfStartOfAssociatedExprs() + + getResultIndex()]); } ArrayRef<Expr *> getAssocExprs() const { return {reinterpret_cast<Expr *const *>(getTrailingObjects<Stmt *>() + - AssocExprStartIndex), + getIndexOfStartOfAssociatedExprs()), NumAssocs}; } ArrayRef<TypeSourceInfo *> getAssocTypeSourceInfos() const { - return {getTrailingObjects<TypeSourceInfo *>(), NumAssocs}; + return {getTrailingObjects<TypeSourceInfo *>() + + getIndexOfStartOfAssociatedTypes(), + NumAssocs}; } /// Return the Ith association expression with its TypeSourceInfo, @@ -5827,23 +6005,30 @@ public: assert(I < getNumAssocs() && "Out-of-range index in GenericSelectionExpr::getAssociation!"); return Association( - cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]), - getTrailingObjects<TypeSourceInfo *>()[I], + cast<Expr>( + getTrailingObjects<Stmt *>()[getIndexOfStartOfAssociatedExprs() + + I]), + getTrailingObjects< + TypeSourceInfo *>()[getIndexOfStartOfAssociatedTypes() + I], !isResultDependent() && (getResultIndex() == I)); } ConstAssociation getAssociation(unsigned I) const { assert(I < getNumAssocs() && "Out-of-range index in GenericSelectionExpr::getAssociation!"); return ConstAssociation( - cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]), - getTrailingObjects<TypeSourceInfo *>()[I], + cast<Expr>( + getTrailingObjects<Stmt *>()[getIndexOfStartOfAssociatedExprs() + + I]), + getTrailingObjects< + TypeSourceInfo *>()[getIndexOfStartOfAssociatedTypes() + I], !isResultDependent() && (getResultIndex() == I)); } association_range associations() { AssociationIterator Begin(getTrailingObjects<Stmt *>() + - AssocExprStartIndex, - getTrailingObjects<TypeSourceInfo *>(), + getIndexOfStartOfAssociatedExprs(), + getTrailingObjects<TypeSourceInfo *>() + + getIndexOfStartOfAssociatedTypes(), /*Offset=*/0, ResultIndex); AssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs, /*Offset=*/NumAssocs, ResultIndex); @@ -5852,8 +6037,9 @@ public: const_association_range associations() const { ConstAssociationIterator Begin(getTrailingObjects<Stmt *>() + - AssocExprStartIndex, - getTrailingObjects<TypeSourceInfo *>(), + getIndexOfStartOfAssociatedExprs(), + getTrailingObjects<TypeSourceInfo *>() + + getIndexOfStartOfAssociatedTypes(), /*Offset=*/0, ResultIndex); ConstAssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs, /*Offset=*/NumAssocs, ResultIndex); @@ -6166,11 +6352,11 @@ public: return getSubExprsBuffer() + getNumSubExprs(); } - llvm::iterator_range<semantics_iterator> semantics() { - return llvm::make_range(semantics_begin(), semantics_end()); + ArrayRef<Expr*> semantics() { + return ArrayRef(semantics_begin(), semantics_end()); } - llvm::iterator_range<const_semantics_iterator> semantics() const { - return llvm::make_range(semantics_begin(), semantics_end()); + ArrayRef<const Expr*> semantics() const { + return ArrayRef(semantics_begin(), semantics_end()); } Expr *getSemanticExpr(unsigned index) { @@ -6272,7 +6458,7 @@ public: return cast<Expr>(SubExprs[ORDER_FAIL]); } Expr *getVal2() const { - if (Op == AO__atomic_exchange) + if (Op == AO__atomic_exchange || Op == AO__scoped_atomic_exchange) return cast<Expr>(SubExprs[ORDER_FAIL]); assert(NumSubExprs > VAL2); return cast<Expr>(SubExprs[VAL2]); @@ -6284,6 +6470,16 @@ public: QualType getValueType() const; AtomicOp getOp() const { return Op; } + StringRef getOpAsString() const { + switch (Op) { +#define BUILTIN(ID, TYPE, ATTRS) +#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ + case AO##ID: \ + return #ID; +#include "clang/Basic/Builtins.def" + } + llvm_unreachable("not an atomic operator?"); + } unsigned getNumSubExprs() const { return NumSubExprs; } Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); } @@ -6298,10 +6494,14 @@ public: bool isCmpXChg() const { return getOp() == AO__c11_atomic_compare_exchange_strong || getOp() == AO__c11_atomic_compare_exchange_weak || + getOp() == AO__hip_atomic_compare_exchange_strong || getOp() == AO__opencl_atomic_compare_exchange_strong || getOp() == AO__opencl_atomic_compare_exchange_weak || + getOp() == AO__hip_atomic_compare_exchange_weak || getOp() == AO__atomic_compare_exchange || - getOp() == AO__atomic_compare_exchange_n; + getOp() == AO__atomic_compare_exchange_n || + getOp() == AO__scoped_atomic_compare_exchange || + getOp() == AO__scoped_atomic_compare_exchange_n; } bool isOpenCL() const { @@ -6331,11 +6531,13 @@ public: /// \return empty atomic scope model if the atomic op code does not have /// scope operand. static std::unique_ptr<AtomicScopeModel> getScopeModel(AtomicOp Op) { - auto Kind = - (Op >= AO__opencl_atomic_load && Op <= AO__opencl_atomic_fetch_max) - ? AtomicScopeModelKind::OpenCL - : AtomicScopeModelKind::None; - return AtomicScopeModel::create(Kind); + if (Op >= AO__opencl_atomic_load && Op <= AO__opencl_atomic_fetch_max) + return AtomicScopeModel::create(AtomicScopeModelKind::OpenCL); + else if (Op >= AO__hip_atomic_load && Op <= AO__hip_atomic_fetch_max) + return AtomicScopeModel::create(AtomicScopeModelKind::HIP); + else if (Op >= AO__scoped_atomic_load && Op <= AO__scoped_atomic_fetch_max) + return AtomicScopeModel::create(AtomicScopeModelKind::Generic); + return AtomicScopeModel::create(AtomicScopeModelKind::None); } /// Get atomic scope model. @@ -6412,7 +6614,7 @@ public: ArrayRef<Expr *> subExpressions() { auto *B = getTrailingObjects<Expr *>(); - return llvm::makeArrayRef(B, B + NumExprs); + return llvm::ArrayRef(B, B + NumExprs); } ArrayRef<const Expr *> subExpressions() const { diff --git a/contrib/llvm-project/clang/include/clang/AST/ExprCXX.h b/contrib/llvm-project/clang/include/clang/AST/ExprCXX.h index 161287adce4c..9a7c632c36c5 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ExprCXX.h +++ b/contrib/llvm-project/clang/include/clang/AST/ExprCXX.h @@ -40,8 +40,6 @@ #include "clang/Basic/Specifiers.h" #include "clang/Basic/TypeTraits.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" @@ -52,6 +50,7 @@ #include <cstddef> #include <cstdint> #include <memory> +#include <optional> namespace clang { @@ -730,6 +729,11 @@ public: explicit CXXBoolLiteralExpr(EmptyShell Empty) : Expr(CXXBoolLiteralExprClass, Empty) {} + static CXXBoolLiteralExpr *Create(const ASTContext &C, bool Val, QualType Ty, + SourceLocation Loc) { + return new (C) CXXBoolLiteralExpr(Val, Ty, Loc); + } + bool getValue() const { return CXXBoolLiteralExprBits.Value; } void setValue(bool V) { CXXBoolLiteralExprBits.Value = V; } @@ -756,6 +760,8 @@ public: /// The null pointer literal (C++11 [lex.nullptr]) /// /// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr. +/// This also implements the null pointer literal in C23 (C23 6.4.1) which is +/// intended to have the same semantics as the feature in C++. class CXXNullPtrLiteralExpr : public Expr { public: CXXNullPtrLiteralExpr(QualType Ty, SourceLocation Loc) @@ -1140,9 +1146,8 @@ public: /// }; /// \endcode class CXXThisExpr : public Expr { -public: - CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit) - : Expr(CXXThisExprClass, Ty, VK_PRValue, OK_Ordinary) { + CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit, ExprValueKind VK) + : Expr(CXXThisExprClass, Ty, VK, OK_Ordinary) { CXXThisExprBits.IsImplicit = IsImplicit; CXXThisExprBits.Loc = L; setDependence(computeDependence(this)); @@ -1150,6 +1155,12 @@ public: CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {} +public: + static CXXThisExpr *Create(const ASTContext &Ctx, SourceLocation L, + QualType Ty, bool IsImplicit); + + static CXXThisExpr *CreateEmpty(const ASTContext &Ctx); + SourceLocation getLocation() const { return CXXThisExprBits.Loc; } void setLocation(SourceLocation L) { CXXThisExprBits.Loc = L; } @@ -1238,8 +1249,12 @@ public: /// This wraps up a function call argument that was created from the /// corresponding parameter's default argument, when the call did not /// explicitly supply arguments for all of the parameters. -class CXXDefaultArgExpr final : public Expr { +class CXXDefaultArgExpr final + : public Expr, + private llvm::TrailingObjects<CXXDefaultArgExpr, Expr *> { friend class ASTStmtReader; + friend class ASTReader; + friend TrailingObjects; /// The parameter whose default is being used. ParmVarDecl *Param; @@ -1248,7 +1263,7 @@ class CXXDefaultArgExpr final : public Expr { DeclContext *UsedContext; CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param, - DeclContext *UsedContext) + Expr *RewrittenExpr, DeclContext *UsedContext) : Expr(SC, Param->hasUnparsedDefaultArg() ? Param->getType().getNonReferenceType() @@ -1257,28 +1272,54 @@ class CXXDefaultArgExpr final : public Expr { Param->getDefaultArg()->getObjectKind()), Param(Param), UsedContext(UsedContext) { CXXDefaultArgExprBits.Loc = Loc; + CXXDefaultArgExprBits.HasRewrittenInit = RewrittenExpr != nullptr; + if (RewrittenExpr) + *getTrailingObjects<Expr *>() = RewrittenExpr; setDependence(computeDependence(this)); } + CXXDefaultArgExpr(EmptyShell Empty, bool HasRewrittenInit) + : Expr(CXXDefaultArgExprClass, Empty) { + CXXDefaultArgExprBits.HasRewrittenInit = HasRewrittenInit; + } + public: - CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} + static CXXDefaultArgExpr *CreateEmpty(const ASTContext &C, + bool HasRewrittenInit); // \p Param is the parameter whose default argument is used by this // expression. static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc, - ParmVarDecl *Param, - DeclContext *UsedContext) { - return new (C) - CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param, UsedContext); - } - + ParmVarDecl *Param, Expr *RewrittenExpr, + DeclContext *UsedContext); // Retrieve the parameter that the argument was created from. const ParmVarDecl *getParam() const { return Param; } ParmVarDecl *getParam() { return Param; } - // Retrieve the actual argument to the function call. - const Expr *getExpr() const { return getParam()->getDefaultArg(); } - Expr *getExpr() { return getParam()->getDefaultArg(); } + bool hasRewrittenInit() const { + return CXXDefaultArgExprBits.HasRewrittenInit; + } + + // Retrieve the argument to the function call. + Expr *getExpr(); + const Expr *getExpr() const { + return const_cast<CXXDefaultArgExpr *>(this)->getExpr(); + } + + Expr *getRewrittenExpr() { + return hasRewrittenInit() ? *getTrailingObjects<Expr *>() : nullptr; + } + + const Expr *getRewrittenExpr() const { + return const_cast<CXXDefaultArgExpr *>(this)->getRewrittenExpr(); + } + + // Retrieve the rewritten init expression (for an init expression containing + // immediate calls) with the top level FullExpr and ConstantExpr stripped off. + Expr *getAdjustedRewrittenExpr(); + const Expr *getAdjustedRewrittenExpr() const { + return const_cast<CXXDefaultArgExpr *>(this)->getAdjustedRewrittenExpr(); + } const DeclContext *getUsedContext() const { return UsedContext; } DeclContext *getUsedContext() { return UsedContext; } @@ -1315,10 +1356,13 @@ public: /// is implicitly used in a mem-initializer-list in a constructor /// (C++11 [class.base.init]p8) or in aggregate initialization /// (C++1y [dcl.init.aggr]p7). -class CXXDefaultInitExpr : public Expr { - friend class ASTReader; - friend class ASTStmtReader; +class CXXDefaultInitExpr final + : public Expr, + private llvm::TrailingObjects<CXXDefaultInitExpr, Expr *> { + friend class ASTStmtReader; + friend class ASTReader; + friend TrailingObjects; /// The field whose default is being used. FieldDecl *Field; @@ -1326,16 +1370,25 @@ class CXXDefaultInitExpr : public Expr { DeclContext *UsedContext; CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc, - FieldDecl *Field, QualType Ty, DeclContext *UsedContext); + FieldDecl *Field, QualType Ty, DeclContext *UsedContext, + Expr *RewrittenInitExpr); - CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {} + CXXDefaultInitExpr(EmptyShell Empty, bool HasRewrittenInit) + : Expr(CXXDefaultInitExprClass, Empty) { + CXXDefaultInitExprBits.HasRewrittenInit = HasRewrittenInit; + } public: + static CXXDefaultInitExpr *CreateEmpty(const ASTContext &C, + bool HasRewrittenInit); /// \p Field is the non-static data member whose default initializer is used /// by this expression. static CXXDefaultInitExpr *Create(const ASTContext &Ctx, SourceLocation Loc, - FieldDecl *Field, DeclContext *UsedContext) { - return new (Ctx) CXXDefaultInitExpr(Ctx, Loc, Field, Field->getType(), UsedContext); + FieldDecl *Field, DeclContext *UsedContext, + Expr *RewrittenInitExpr); + + bool hasRewrittenInit() const { + return CXXDefaultInitExprBits.HasRewrittenInit; } /// Get the field whose initializer will be used. @@ -1343,13 +1396,23 @@ public: const FieldDecl *getField() const { return Field; } /// Get the initialization expression that will be used. + Expr *getExpr(); const Expr *getExpr() const { - assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); - return Field->getInClassInitializer(); + return const_cast<CXXDefaultInitExpr *>(this)->getExpr(); } - Expr *getExpr() { - assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); - return Field->getInClassInitializer(); + + /// Retrieve the initializing expression with evaluated immediate calls, if + /// any. + const Expr *getRewrittenExpr() const { + assert(hasRewrittenInit() && "expected a rewritten init expression"); + return *getTrailingObjects<Expr *>(); + } + + /// Retrieve the initializing expression with evaluated immediate calls, if + /// any. + Expr *getRewrittenExpr() { + assert(hasRewrittenInit() && "expected a rewritten init expression"); + return *getTrailingObjects<Expr *>(); } const DeclContext *getUsedContext() const { return UsedContext; } @@ -1456,19 +1519,17 @@ public: } }; +enum class CXXConstructionKind { + Complete, + NonVirtualBase, + VirtualBase, + Delegating +}; + /// Represents a call to a C++ constructor. class CXXConstructExpr : public Expr { friend class ASTStmtReader; -public: - enum ConstructionKind { - CK_Complete, - CK_NonVirtualBase, - CK_VirtualBase, - CK_Delegating - }; - -private: /// A pointer to the constructor which will be ultimately called. CXXConstructorDecl *Constructor; @@ -1504,7 +1565,7 @@ protected: CXXConstructorDecl *Ctor, bool Elidable, ArrayRef<Expr *> Args, bool HadMultipleCandidates, bool ListInitialization, bool StdInitListInitialization, - bool ZeroInitialization, ConstructionKind ConstructKind, + bool ZeroInitialization, CXXConstructionKind ConstructKind, SourceRange ParenOrBraceRange); /// Build an empty C++ construction expression. @@ -1523,7 +1584,7 @@ public: CXXConstructorDecl *Ctor, bool Elidable, ArrayRef<Expr *> Args, bool HadMultipleCandidates, bool ListInitialization, bool StdInitListInitialization, bool ZeroInitialization, - ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); + CXXConstructionKind ConstructKind, SourceRange ParenOrBraceRange); /// Create an empty C++ construction expression. static CXXConstructExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs); @@ -1577,11 +1638,12 @@ public: /// Determine whether this constructor is actually constructing /// a base class (rather than a complete object). - ConstructionKind getConstructionKind() const { - return static_cast<ConstructionKind>(CXXConstructExprBits.ConstructionKind); + CXXConstructionKind getConstructionKind() const { + return static_cast<CXXConstructionKind>( + CXXConstructExprBits.ConstructionKind); } - void setConstructionKind(ConstructionKind CK) { - CXXConstructExprBits.ConstructionKind = CK; + void setConstructionKind(CXXConstructionKind CK) { + CXXConstructExprBits.ConstructionKind = llvm::to_underlying(CK); } using arg_iterator = ExprIterator; @@ -1623,6 +1685,14 @@ public: getArgs()[Arg] = ArgExpr; } + bool isImmediateEscalating() const { + return CXXConstructExprBits.IsImmediateEscalating; + } + + void setIsImmediateEscalating(bool Set) { + CXXConstructExprBits.IsImmediateEscalating = Set; + } + SourceLocation getBeginLoc() const LLVM_READONLY; SourceLocation getEndLoc() const LLVM_READONLY; SourceRange getParenOrBraceRange() const { return ParenOrBraceRange; } @@ -1656,10 +1726,12 @@ private: SourceLocation Loc; /// Whether this is the construction of a virtual base. + LLVM_PREFERRED_TYPE(bool) unsigned ConstructsVirtualBase : 1; /// Whether the constructor is inherited from a virtual base class of the /// class that we construct. + LLVM_PREFERRED_TYPE(bool) unsigned InheritedFromVirtualBase : 1; public: @@ -1688,9 +1760,9 @@ public: /// Determine whether this constructor is actually constructing /// a base class (rather than a complete object). bool constructsVBase() const { return ConstructsVirtualBase; } - CXXConstructExpr::ConstructionKind getConstructionKind() const { - return ConstructsVirtualBase ? CXXConstructExpr::CK_VirtualBase - : CXXConstructExpr::CK_NonVirtualBase; + CXXConstructionKind getConstructionKind() const { + return ConstructsVirtualBase ? CXXConstructionKind::VirtualBase + : CXXConstructionKind::NonVirtualBase; } /// Determine whether the inherited constructor is inherited from a @@ -2134,6 +2206,17 @@ public: } }; +enum class CXXNewInitializationStyle { + /// New-expression has no initializer as written. + None, + + /// New-expression has a C++98 paren-delimited initializer. + Parens, + + /// New-expression has a C++11 list-initializer. + Braces +}; + /// Represents a new-expression for memory allocation and constructor /// calls, e.g: "new CXXNewExpr(foo)". class CXXNewExpr final @@ -2187,25 +2270,12 @@ class CXXNewExpr final return isParenTypeId(); } -public: - enum InitializationStyle { - /// New-expression has no initializer as written. - NoInit, - - /// New-expression has a C++98 paren-delimited initializer. - CallInit, - - /// New-expression has a C++11 list-initializer. - ListInit - }; - -private: /// Build a c++ new expression. CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, FunctionDecl *OperatorDelete, bool ShouldPassAlignment, bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs, - SourceRange TypeIdParens, Optional<Expr *> ArraySize, - InitializationStyle InitializationStyle, Expr *Initializer, + SourceRange TypeIdParens, std::optional<Expr *> ArraySize, + CXXNewInitializationStyle InitializationStyle, Expr *Initializer, QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange DirectInitRange); @@ -2219,8 +2289,8 @@ public: Create(const ASTContext &Ctx, bool IsGlobalNew, FunctionDecl *OperatorNew, FunctionDecl *OperatorDelete, bool ShouldPassAlignment, bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs, - SourceRange TypeIdParens, Optional<Expr *> ArraySize, - InitializationStyle InitializationStyle, Expr *Initializer, + SourceRange TypeIdParens, std::optional<Expr *> ArraySize, + CXXNewInitializationStyle InitializationStyle, Expr *Initializer, QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange DirectInitRange); @@ -2261,15 +2331,32 @@ public: bool isArray() const { return CXXNewExprBits.IsArray; } - Optional<Expr *> getArraySize() { + /// This might return std::nullopt even if isArray() returns true, + /// since there might not be an array size expression. + /// If the result is not std::nullopt, it will never wrap a nullptr. + std::optional<Expr *> getArraySize() { if (!isArray()) - return None; - return cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]); + return std::nullopt; + + if (auto *Result = + cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()])) + return Result; + + return std::nullopt; } - Optional<const Expr *> getArraySize() const { + + /// This might return std::nullopt even if isArray() returns true, + /// since there might not be an array size expression. + /// If the result is not std::nullopt, it will never wrap a nullptr. + std::optional<const Expr *> getArraySize() const { if (!isArray()) - return None; - return cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]); + return std::nullopt; + + if (auto *Result = + cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()])) + return Result; + + return std::nullopt; } unsigned getNumPlacementArgs() const { @@ -2298,16 +2385,12 @@ public: bool isGlobalNew() const { return CXXNewExprBits.IsGlobalNew; } /// Whether this new-expression has any initializer at all. - bool hasInitializer() const { - return CXXNewExprBits.StoredInitializationStyle > 0; - } + bool hasInitializer() const { return CXXNewExprBits.HasInitializer; } /// The kind of initializer this new-expression has. - InitializationStyle getInitializationStyle() const { - if (CXXNewExprBits.StoredInitializationStyle == 0) - return NoInit; - return static_cast<InitializationStyle>( - CXXNewExprBits.StoredInitializationStyle - 1); + CXXNewInitializationStyle getInitializationStyle() const { + return static_cast<CXXNewInitializationStyle>( + CXXNewExprBits.StoredInitializationStyle); } /// The initializer of this new-expression. @@ -2522,6 +2605,7 @@ class CXXPseudoDestructorExpr : public Expr { /// Whether the operator was an arrow ('->'); otherwise, it was a /// period ('.'). + LLVM_PREFERRED_TYPE(bool) bool IsArrow : 1; /// The location of the '.' or '->' operator. @@ -2721,8 +2805,7 @@ public: /// Retrieve the argument types. ArrayRef<TypeSourceInfo *> getArgs() const { - return llvm::makeArrayRef(getTrailingObjects<TypeSourceInfo *>(), - getNumArgs()); + return llvm::ArrayRef(getTrailingObjects<TypeSourceInfo *>(), getNumArgs()); } SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } @@ -2752,6 +2835,7 @@ public: /// \endcode class ArrayTypeTraitExpr : public Expr { /// The trait. An ArrayTypeTrait enum in MSVC compat unsigned. + LLVM_PREFERRED_TYPE(ArrayTypeTrait) unsigned ATT : 2; /// The value of the type trait. Unspecified if dependent. @@ -2822,9 +2906,11 @@ public: /// \endcode class ExpressionTraitExpr : public Expr { /// The trait. A ExpressionTrait enum in MSVC compatible unsigned. + LLVM_PREFERRED_TYPE(ExpressionTrait) unsigned ET : 31; /// The value of the type trait. Unspecified if dependent. + LLVM_PREFERRED_TYPE(bool) unsigned Value : 1; /// The location of the type trait keyword. @@ -3104,7 +3190,8 @@ class UnresolvedLookupExpr final const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, UnresolvedSetIterator End); + UnresolvedSetIterator Begin, UnresolvedSetIterator End, + bool KnownDependent); UnresolvedLookupExpr(EmptyShell Empty, unsigned NumResults, bool HasTemplateKWAndArgsInfo); @@ -3124,12 +3211,15 @@ public: const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin, UnresolvedSetIterator End); + // After canonicalization, there may be dependent template arguments in + // CanonicalConverted But none of Args is dependent. When any of + // CanonicalConverted dependent, KnownDependent is true. static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, - UnresolvedSetIterator End); + UnresolvedSetIterator End, bool KnownDependent); static UnresolvedLookupExpr *CreateEmpty(const ASTContext &Context, unsigned NumResults, @@ -3368,8 +3458,7 @@ public: ArrayRef<CleanupObject> objects); ArrayRef<CleanupObject> getObjects() const { - return llvm::makeArrayRef(getTrailingObjects<CleanupObject>(), - getNumObjects()); + return llvm::ArrayRef(getTrailingObjects<CleanupObject>(), getNumObjects()); } unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; } @@ -3431,8 +3520,9 @@ class CXXUnresolvedConstructExpr final friend class ASTStmtReader; friend TrailingObjects; - /// The type being constructed. - TypeSourceInfo *TSI; + /// The type being constructed, and whether the construct expression models + /// list initialization or not. + llvm::PointerIntPair<TypeSourceInfo *, 1> TypeAndInitForm; /// The location of the left parentheses ('('). SourceLocation LParenLoc; @@ -3442,30 +3532,31 @@ class CXXUnresolvedConstructExpr final CXXUnresolvedConstructExpr(QualType T, TypeSourceInfo *TSI, SourceLocation LParenLoc, ArrayRef<Expr *> Args, - SourceLocation RParenLoc); + SourceLocation RParenLoc, bool IsListInit); CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs) - : Expr(CXXUnresolvedConstructExprClass, Empty), TSI(nullptr) { + : Expr(CXXUnresolvedConstructExprClass, Empty) { CXXUnresolvedConstructExprBits.NumArgs = NumArgs; } public: - static CXXUnresolvedConstructExpr *Create(const ASTContext &Context, - QualType T, TypeSourceInfo *TSI, - SourceLocation LParenLoc, - ArrayRef<Expr *> Args, - SourceLocation RParenLoc); + static CXXUnresolvedConstructExpr * + Create(const ASTContext &Context, QualType T, TypeSourceInfo *TSI, + SourceLocation LParenLoc, ArrayRef<Expr *> Args, + SourceLocation RParenLoc, bool IsListInit); static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &Context, unsigned NumArgs); /// Retrieve the type that is being constructed, as specified /// in the source code. - QualType getTypeAsWritten() const { return TSI->getType(); } + QualType getTypeAsWritten() const { return getTypeSourceInfo()->getType(); } /// Retrieve the type source information for the type being /// constructed. - TypeSourceInfo *getTypeSourceInfo() const { return TSI; } + TypeSourceInfo *getTypeSourceInfo() const { + return TypeAndInitForm.getPointer(); + } /// Retrieve the location of the left parentheses ('(') that /// precedes the argument list. @@ -3480,7 +3571,7 @@ public: /// Determine whether this expression models list-initialization. /// If so, there will be exactly one subexpression, which will be /// an InitListExpr. - bool isListInitialization() const { return LParenLoc.isInvalid(); } + bool isListInitialization() const { return TypeAndInitForm.getInt(); } /// Retrieve the number of arguments. unsigned getNumArgs() const { return CXXUnresolvedConstructExprBits.NumArgs; } @@ -4065,7 +4156,7 @@ class PackExpansionExpr : public Expr { public: PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc, - Optional<unsigned> NumExpansions) + std::optional<unsigned> NumExpansions) : Expr(PackExpansionExprClass, T, Pattern->getValueKind(), Pattern->getObjectKind()), EllipsisLoc(EllipsisLoc), @@ -4088,11 +4179,11 @@ public: /// Determine the number of expansions that will be produced when /// this pack expansion is instantiated, if already known. - Optional<unsigned> getNumExpansions() const { + std::optional<unsigned> getNumExpansions() const { if (NumExpansions) return NumExpansions - 1; - return None; + return std::nullopt; } SourceLocation getBeginLoc() const LLVM_READONLY { @@ -4159,7 +4250,7 @@ class SizeOfPackExpr final /// the given parameter pack. SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, SourceLocation PackLoc, SourceLocation RParenLoc, - Optional<unsigned> Length, + std::optional<unsigned> Length, ArrayRef<TemplateArgument> PartialArgs) : Expr(SizeOfPackExprClass, SizeType, VK_PRValue, OK_Ordinary), OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), @@ -4177,11 +4268,11 @@ class SizeOfPackExpr final : Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs) {} public: - static SizeOfPackExpr *Create(ASTContext &Context, SourceLocation OperatorLoc, - NamedDecl *Pack, SourceLocation PackLoc, - SourceLocation RParenLoc, - Optional<unsigned> Length = None, - ArrayRef<TemplateArgument> PartialArgs = None); + static SizeOfPackExpr * + Create(ASTContext &Context, SourceLocation OperatorLoc, NamedDecl *Pack, + SourceLocation PackLoc, SourceLocation RParenLoc, + std::optional<unsigned> Length = std::nullopt, + ArrayRef<TemplateArgument> PartialArgs = std::nullopt); static SizeOfPackExpr *CreateDeserialized(ASTContext &Context, unsigned NumPartialArgs); @@ -4220,7 +4311,7 @@ public: ArrayRef<TemplateArgument> getPartialArguments() const { assert(isPartiallySubstituted()); const auto *Args = getTrailingObjects<TemplateArgument>(); - return llvm::makeArrayRef(Args, Args + Length); + return llvm::ArrayRef(Args, Args + Length); } SourceLocation getBeginLoc() const LLVM_READONLY { return OperatorLoc; } @@ -4246,24 +4337,30 @@ class SubstNonTypeTemplateParmExpr : public Expr { friend class ASTReader; friend class ASTStmtReader; - /// The replaced parameter and a flag indicating if it was a reference + /// The replacement expression. + Stmt *Replacement; + + /// The associated declaration and a flag indicating if it was a reference /// parameter. For class NTTPs, we can't determine that based on the value /// category alone. - llvm::PointerIntPair<NonTypeTemplateParmDecl*, 1, bool> ParamAndRef; + llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndRef; - /// The replacement expression. - Stmt *Replacement; + unsigned Index : 15; + unsigned PackIndex : 16; explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty) : Expr(SubstNonTypeTemplateParmExprClass, Empty) {} public: SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind, - SourceLocation Loc, - NonTypeTemplateParmDecl *Param, bool RefParam, - Expr *Replacement) + SourceLocation Loc, Expr *Replacement, + Decl *AssociatedDecl, unsigned Index, + std::optional<unsigned> PackIndex, bool RefParam) : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary), - ParamAndRef(Param, RefParam), Replacement(Replacement) { + Replacement(Replacement), + AssociatedDeclAndRef(AssociatedDecl, RefParam), Index(Index), + PackIndex(PackIndex ? *PackIndex + 1 : 0) { + assert(AssociatedDecl != nullptr); SubstNonTypeTemplateParmExprBits.NameLoc = Loc; setDependence(computeDependence(this)); } @@ -4276,11 +4373,23 @@ public: Expr *getReplacement() const { return cast<Expr>(Replacement); } - NonTypeTemplateParmDecl *getParameter() const { - return ParamAndRef.getPointer(); + /// A template-like entity which owns the whole pattern being substituted. + /// This will own a set of template parameters. + Decl *getAssociatedDecl() const { return AssociatedDeclAndRef.getPointer(); } + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getParameter()->getIndex()`. + unsigned getIndex() const { return Index; } + + std::optional<unsigned> getPackIndex() const { + if (PackIndex == 0) + return std::nullopt; + return PackIndex - 1; } - bool isReferenceParameter() const { return ParamAndRef.getInt(); } + NonTypeTemplateParmDecl *getParameter() const; + + bool isReferenceParameter() const { return AssociatedDeclAndRef.getInt(); } /// Determine the substituted type of the template parameter. QualType getParameterType(const ASTContext &Ctx) const; @@ -4314,14 +4423,16 @@ class SubstNonTypeTemplateParmPackExpr : public Expr { friend class ASTStmtReader; /// The non-type template parameter pack itself. - NonTypeTemplateParmDecl *Param; + Decl *AssociatedDecl; /// A pointer to the set of template arguments that this /// parameter pack is instantiated with. const TemplateArgument *Arguments; /// The number of template arguments in \c Arguments. - unsigned NumArguments; + unsigned NumArguments : 16; + + unsigned Index : 16; /// The location of the non-type template parameter pack reference. SourceLocation NameLoc; @@ -4330,14 +4441,21 @@ class SubstNonTypeTemplateParmPackExpr : public Expr { : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) {} public: - SubstNonTypeTemplateParmPackExpr(QualType T, - ExprValueKind ValueKind, - NonTypeTemplateParmDecl *Param, + SubstNonTypeTemplateParmPackExpr(QualType T, ExprValueKind ValueKind, SourceLocation NameLoc, - const TemplateArgument &ArgPack); + const TemplateArgument &ArgPack, + Decl *AssociatedDecl, unsigned Index); + + /// A template-like entity which owns the whole pattern being substituted. + /// This will own a set of template parameters. + Decl *getAssociatedDecl() const { return AssociatedDecl; } + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getParameterPack()->getIndex()`. + unsigned getIndex() const { return Index; } /// Retrieve the non-type template parameter pack being substituted. - NonTypeTemplateParmDecl *getParameterPack() const { return Param; } + NonTypeTemplateParmDecl *getParameterPack() const; /// Retrieve the location of the parameter pack name. SourceLocation getParameterPackLocation() const { return NameLoc; } @@ -4590,7 +4708,7 @@ public: CXXFoldExpr(QualType T, UnresolvedLookupExpr *Callee, SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr *RHS, SourceLocation RParenLoc, - Optional<unsigned> NumExpansions) + std::optional<unsigned> NumExpansions) : Expr(CXXFoldExprClass, T, VK_PRValue, OK_Ordinary), LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc), NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), Opcode(Opcode) { @@ -4627,10 +4745,10 @@ public: SourceLocation getEllipsisLoc() const { return EllipsisLoc; } BinaryOperatorKind getOperator() const { return Opcode; } - Optional<unsigned> getNumExpansions() const { + std::optional<unsigned> getNumExpansions() const { if (NumExpansions) return NumExpansions - 1; - return None; + return std::nullopt; } SourceLocation getBeginLoc() const LLVM_READONLY { @@ -4663,6 +4781,140 @@ public: } }; +/// Represents a list-initialization with parenthesis. +/// +/// As per P0960R3, this is a C++20 feature that allows aggregate to +/// be initialized with a parenthesized list of values: +/// ``` +/// struct A { +/// int a; +/// double b; +/// }; +/// +/// void foo() { +/// A a1(0); // Well-formed in C++20 +/// A a2(1.5, 1.0); // Well-formed in C++20 +/// } +/// ``` +/// It has some sort of similiarity to braced +/// list-initialization, with some differences such as +/// it allows narrowing conversion whilst braced +/// list-initialization doesn't. +/// ``` +/// struct A { +/// char a; +/// }; +/// void foo() { +/// A a(1.5); // Well-formed in C++20 +/// A b{1.5}; // Ill-formed ! +/// } +/// ``` +class CXXParenListInitExpr final + : public Expr, + private llvm::TrailingObjects<CXXParenListInitExpr, Expr *> { + friend class TrailingObjects; + friend class ASTStmtReader; + friend class ASTStmtWriter; + + unsigned NumExprs; + unsigned NumUserSpecifiedExprs; + SourceLocation InitLoc, LParenLoc, RParenLoc; + llvm::PointerUnion<Expr *, FieldDecl *> ArrayFillerOrUnionFieldInit; + + CXXParenListInitExpr(ArrayRef<Expr *> Args, QualType T, + unsigned NumUserSpecifiedExprs, SourceLocation InitLoc, + SourceLocation LParenLoc, SourceLocation RParenLoc) + : Expr(CXXParenListInitExprClass, T, getValueKindForType(T), OK_Ordinary), + NumExprs(Args.size()), NumUserSpecifiedExprs(NumUserSpecifiedExprs), + InitLoc(InitLoc), LParenLoc(LParenLoc), RParenLoc(RParenLoc) { + std::copy(Args.begin(), Args.end(), getTrailingObjects<Expr *>()); + assert(NumExprs >= NumUserSpecifiedExprs && + "number of user specified inits is greater than the number of " + "passed inits"); + setDependence(computeDependence(this)); + } + + size_t numTrailingObjects(OverloadToken<Expr *>) const { return NumExprs; } + +public: + static CXXParenListInitExpr * + Create(ASTContext &C, ArrayRef<Expr *> Args, QualType T, + unsigned NumUserSpecifiedExprs, SourceLocation InitLoc, + SourceLocation LParenLoc, SourceLocation RParenLoc); + + static CXXParenListInitExpr *CreateEmpty(ASTContext &C, unsigned numExprs, + EmptyShell Empty); + + explicit CXXParenListInitExpr(EmptyShell Empty, unsigned NumExprs) + : Expr(CXXParenListInitExprClass, Empty), NumExprs(NumExprs), + NumUserSpecifiedExprs(0) {} + + void updateDependence() { setDependence(computeDependence(this)); } + + ArrayRef<Expr *> getInitExprs() { + return ArrayRef(getTrailingObjects<Expr *>(), NumExprs); + } + + const ArrayRef<Expr *> getInitExprs() const { + return ArrayRef(getTrailingObjects<Expr *>(), NumExprs); + } + + ArrayRef<Expr *> getUserSpecifiedInitExprs() { + return ArrayRef(getTrailingObjects<Expr *>(), NumUserSpecifiedExprs); + } + + const ArrayRef<Expr *> getUserSpecifiedInitExprs() const { + return ArrayRef(getTrailingObjects<Expr *>(), NumUserSpecifiedExprs); + } + + SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; } + + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + + SourceLocation getInitLoc() const LLVM_READONLY { return InitLoc; } + + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(getBeginLoc(), getEndLoc()); + } + + void setArrayFiller(Expr *E) { ArrayFillerOrUnionFieldInit = E; } + + Expr *getArrayFiller() { + return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>(); + } + + const Expr *getArrayFiller() const { + return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>(); + } + + void setInitializedFieldInUnion(FieldDecl *FD) { + ArrayFillerOrUnionFieldInit = FD; + } + + FieldDecl *getInitializedFieldInUnion() { + return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>(); + } + + const FieldDecl *getInitializedFieldInUnion() const { + return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>(); + } + + child_range children() { + Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()); + return child_range(Begin, Begin + NumExprs); + } + + const_child_range children() const { + Stmt *const *Begin = + reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>()); + return const_child_range(Begin, Begin + NumExprs); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXParenListInitExprClass; + } +}; + /// Represents an expression that might suspend coroutine execution; /// either a co_await or co_yield expression. /// @@ -4681,18 +4933,19 @@ class CoroutineSuspendExpr : public Expr { SourceLocation KeywordLoc; - enum SubExpr { Common, Ready, Suspend, Resume, Count }; + enum SubExpr { Operand, Common, Ready, Suspend, Resume, Count }; Stmt *SubExprs[SubExpr::Count]; OpaqueValueExpr *OpaqueValue = nullptr; public: - CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Common, - Expr *Ready, Expr *Suspend, Expr *Resume, + CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Operand, + Expr *Common, Expr *Ready, Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue) : Expr(SC, Resume->getType(), Resume->getValueKind(), Resume->getObjectKind()), KeywordLoc(KeywordLoc), OpaqueValue(OpaqueValue) { + SubExprs[SubExpr::Operand] = Operand; SubExprs[SubExpr::Common] = Common; SubExprs[SubExpr::Ready] = Ready; SubExprs[SubExpr::Suspend] = Suspend; @@ -4701,10 +4954,11 @@ public: } CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, QualType Ty, - Expr *Common) + Expr *Operand, Expr *Common) : Expr(SC, Ty, VK_PRValue, OK_Ordinary), KeywordLoc(KeywordLoc) { assert(Common->isTypeDependent() && Ty->isDependentType() && "wrong constructor for non-dependent co_await/co_yield expression"); + SubExprs[SubExpr::Operand] = Operand; SubExprs[SubExpr::Common] = Common; SubExprs[SubExpr::Ready] = nullptr; SubExprs[SubExpr::Suspend] = nullptr; @@ -4713,14 +4967,13 @@ public: } CoroutineSuspendExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { + SubExprs[SubExpr::Operand] = nullptr; SubExprs[SubExpr::Common] = nullptr; SubExprs[SubExpr::Ready] = nullptr; SubExprs[SubExpr::Suspend] = nullptr; SubExprs[SubExpr::Resume] = nullptr; } - SourceLocation getKeywordLoc() const { return KeywordLoc; } - Expr *getCommonExpr() const { return static_cast<Expr*>(SubExprs[SubExpr::Common]); } @@ -4740,10 +4993,17 @@ public: return static_cast<Expr*>(SubExprs[SubExpr::Resume]); } + // The syntactic operand written in the code + Expr *getOperand() const { + return static_cast<Expr *>(SubExprs[SubExpr::Operand]); + } + + SourceLocation getKeywordLoc() const { return KeywordLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; } SourceLocation getEndLoc() const LLVM_READONLY { - return getCommonExpr()->getEndLoc(); + return getOperand()->getEndLoc(); } child_range children() { @@ -4765,28 +5025,24 @@ class CoawaitExpr : public CoroutineSuspendExpr { friend class ASTStmtReader; public: - CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Ready, - Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue, - bool IsImplicit = false) - : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Ready, - Suspend, Resume, OpaqueValue) { + CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Common, + Expr *Ready, Expr *Suspend, Expr *Resume, + OpaqueValueExpr *OpaqueValue, bool IsImplicit = false) + : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Common, + Ready, Suspend, Resume, OpaqueValue) { CoawaitBits.IsImplicit = IsImplicit; } CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand, - bool IsImplicit = false) - : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) { + Expr *Common, bool IsImplicit = false) + : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand, + Common) { CoawaitBits.IsImplicit = IsImplicit; } CoawaitExpr(EmptyShell Empty) : CoroutineSuspendExpr(CoawaitExprClass, Empty) {} - Expr *getOperand() const { - // FIXME: Dig out the actual operand or store it. - return getCommonExpr(); - } - bool isImplicit() const { return CoawaitBits.IsImplicit; } void setIsImplicit(bool value = true) { CoawaitBits.IsImplicit = value; } @@ -4850,20 +5106,18 @@ class CoyieldExpr : public CoroutineSuspendExpr { friend class ASTStmtReader; public: - CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Ready, - Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue) - : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Ready, - Suspend, Resume, OpaqueValue) {} - CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand) - : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand) {} + CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Common, + Expr *Ready, Expr *Suspend, Expr *Resume, + OpaqueValueExpr *OpaqueValue) + : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Common, + Ready, Suspend, Resume, OpaqueValue) {} + CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand, + Expr *Common) + : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand, + Common) {} CoyieldExpr(EmptyShell Empty) : CoroutineSuspendExpr(CoyieldExprClass, Empty) {} - Expr *getOperand() const { - // FIXME: Dig out the actual operand or store it. - return getCommonExpr(); - } - static bool classof(const Stmt *T) { return T->getStmtClass() == CoyieldExprClass; } diff --git a/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h b/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h index 1544c498ef66..29913fd84c58 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h +++ b/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h @@ -14,19 +14,21 @@ #ifndef LLVM_CLANG_AST_EXPRCONCEPTS_H #define LLVM_CLANG_AST_EXPRCONCEPTS_H -#include "clang/AST/ASTContext.h" #include "clang/AST/ASTConcept.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclarationName.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/STLFunctionalExtras.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TrailingObjects.h" -#include <utility> #include <string> +#include <utility> namespace clang { class ASTStmtReader; @@ -37,74 +39,91 @@ class ASTStmtWriter; /// /// According to C++2a [expr.prim.id]p3 an id-expression that denotes the /// specialization of a concept results in a prvalue of type bool. -class ConceptSpecializationExpr final : public Expr, public ConceptReference, - private llvm::TrailingObjects<ConceptSpecializationExpr, - TemplateArgument> { +class ConceptSpecializationExpr final : public Expr { + friend class ASTReader; friend class ASTStmtReader; - friend TrailingObjects; -public: - using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>; -protected: - /// \brief The number of template arguments in the tail-allocated list of - /// converted template arguments. - unsigned NumTemplateArgs; +private: + ConceptReference *ConceptRef; + + /// \brief The Implicit Concept Specialization Decl, which holds the template + /// arguments for this specialization. + ImplicitConceptSpecializationDecl *SpecDecl; /// \brief Information about the satisfaction of the named concept with the /// given arguments. If this expression is value dependent, this is to be /// ignored. ASTConstraintSatisfaction *Satisfaction; - ConceptSpecializationExpr(const ASTContext &C, NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, - DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - ArrayRef<TemplateArgument> ConvertedArgs, + ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef, + ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction); - ConceptSpecializationExpr(const ASTContext &C, ConceptDecl *NamedConcept, - ArrayRef<TemplateArgument> ConvertedArgs, + ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef, + ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction, bool Dependent, bool ContainsUnexpandedParameterPack); - - ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs); + ConceptSpecializationExpr(EmptyShell Empty); public: - static ConceptSpecializationExpr * - Create(const ASTContext &C, NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - ArrayRef<TemplateArgument> ConvertedArgs, + Create(const ASTContext &C, ConceptReference *ConceptRef, + ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction); static ConceptSpecializationExpr * - Create(const ASTContext &C, ConceptDecl *NamedConcept, - ArrayRef<TemplateArgument> ConvertedArgs, - const ConstraintSatisfaction *Satisfaction, - bool Dependent, + Create(const ASTContext &C, ConceptReference *ConceptRef, + ImplicitConceptSpecializationDecl *SpecDecl, + const ConstraintSatisfaction *Satisfaction, bool Dependent, bool ContainsUnexpandedParameterPack); - static ConceptSpecializationExpr * - Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs); - ArrayRef<TemplateArgument> getTemplateArguments() const { - return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(), - NumTemplateArgs); + return SpecDecl->getTemplateArguments(); + } + + ConceptReference *getConceptReference() const { return ConceptRef; } + + ConceptDecl *getNamedConcept() const { return ConceptRef->getNamedConcept(); } + + // FIXME: Several of the following functions can be removed. Instead the + // caller can directly work with the ConceptReference. + bool hasExplicitTemplateArgs() const { + return ConceptRef->hasExplicitTemplateArgs(); + } + + SourceLocation getConceptNameLoc() const { + return ConceptRef->getConceptNameLoc(); + } + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { + return ConceptRef->getTemplateArgsAsWritten(); + } + + const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { + return ConceptRef->getNestedNameSpecifierLoc(); + } + + SourceLocation getTemplateKWLoc() const { + return ConceptRef->getTemplateKWLoc(); } - /// \brief Set new template arguments for this concept specialization. - void setTemplateArguments(ArrayRef<TemplateArgument> Converted); + NamedDecl *getFoundDecl() const { return ConceptRef->getFoundDecl(); } + + const DeclarationNameInfo &getConceptNameInfo() const { + return ConceptRef->getConceptNameInfo(); + } + + const ImplicitConceptSpecializationDecl *getSpecializationDecl() const { + assert(SpecDecl && "Template Argument Decl not initialized"); + return SpecDecl; + } /// \brief Whether or not the concept with the given arguments was satisfied /// when the expression was created. /// The expression must not be dependent. bool isSatisfied() const { - assert(!isValueDependent() - && "isSatisfied called on a dependent ConceptSpecializationExpr"); + assert(!isValueDependent() && + "isSatisfied called on a dependent ConceptSpecializationExpr"); return Satisfaction->IsSatisfied; } @@ -112,8 +131,8 @@ public: /// satisfaction of the named concept. /// The expression must not be dependent. const ASTConstraintSatisfaction &getSatisfaction() const { - assert(!isValueDependent() - && "getSatisfaction called on dependent ConceptSpecializationExpr"); + assert(!isValueDependent() && + "getSatisfaction called on dependent ConceptSpecializationExpr"); return *Satisfaction; } @@ -122,15 +141,15 @@ public: } SourceLocation getBeginLoc() const LLVM_READONLY { - return ConceptName.getBeginLoc(); + return ConceptRef->getBeginLoc(); } SourceLocation getEndLoc() const LLVM_READONLY { - // If the ConceptSpecializationExpr is the ImmediatelyDeclaredConstraint - // of a TypeConstraint written syntactically as a constrained-parameter, - // there may not be a template argument list. - return ArgsAsWritten->RAngleLoc.isValid() ? ArgsAsWritten->RAngleLoc - : ConceptName.getEndLoc(); + return ConceptRef->getEndLoc(); + } + + SourceLocation getExprLoc() const LLVM_READONLY { + return ConceptRef->getLocation(); } // Iterators @@ -154,8 +173,11 @@ public: private: const RequirementKind Kind; // FIXME: use RequirementDependence to model dependence? + LLVM_PREFERRED_TYPE(bool) bool Dependent : 1; + LLVM_PREFERRED_TYPE(bool) bool ContainsUnexpandedParameterPack : 1; + LLVM_PREFERRED_TYPE(bool) bool Satisfied : 1; public: struct SubstitutionDiagnostic { @@ -275,12 +297,12 @@ public: friend ASTStmtWriter; /// \brief No return type requirement was specified. - ReturnTypeRequirement() : TypeConstraintInfo(nullptr, 0) {} + ReturnTypeRequirement() : TypeConstraintInfo(nullptr, false) {} /// \brief A return type requirement was specified but it was a /// substitution failure. ReturnTypeRequirement(SubstitutionDiagnostic *SubstDiag) : - TypeConstraintInfo(SubstDiag, 0) {} + TypeConstraintInfo(SubstDiag, false) {} /// \brief A 'type constraint' style return type requirement. /// \param TPL an invented template parameter list containing a single @@ -405,57 +427,61 @@ public: /// \brief A requires-expression requirement which is satisfied when a general /// constraint expression is satisfied ('nested' requirements). class NestedRequirement : public Requirement { - llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> Value; + Expr *Constraint = nullptr; const ASTConstraintSatisfaction *Satisfaction = nullptr; + bool HasInvalidConstraint = false; + StringRef InvalidConstraintEntity; public: friend ASTStmtReader; friend ASTStmtWriter; - NestedRequirement(SubstitutionDiagnostic *SubstDiag) : - Requirement(RK_Nested, /*Dependent=*/false, - /*ContainsUnexpandedParameterPack*/false, - /*Satisfied=*/false), Value(SubstDiag) {} - - NestedRequirement(Expr *Constraint) : - Requirement(RK_Nested, /*Dependent=*/true, - Constraint->containsUnexpandedParameterPack()), - Value(Constraint) { + NestedRequirement(Expr *Constraint) + : Requirement(RK_Nested, /*IsDependent=*/true, + Constraint->containsUnexpandedParameterPack()), + Constraint(Constraint) { assert(Constraint->isInstantiationDependent() && "Nested requirement with non-dependent constraint must be " "constructed with a ConstraintSatisfaction object"); } NestedRequirement(ASTContext &C, Expr *Constraint, - const ConstraintSatisfaction &Satisfaction) : - Requirement(RK_Nested, Constraint->isInstantiationDependent(), - Constraint->containsUnexpandedParameterPack(), - Satisfaction.IsSatisfied), - Value(Constraint), - Satisfaction(ASTConstraintSatisfaction::Create(C, Satisfaction)) {} - - bool isSubstitutionFailure() const { - return Value.is<SubstitutionDiagnostic *>(); - } - - SubstitutionDiagnostic *getSubstitutionDiagnostic() const { - assert(isSubstitutionFailure() && - "getSubstitutionDiagnostic() may not be called when there was no " - "substitution failure."); - return Value.get<SubstitutionDiagnostic *>(); + const ConstraintSatisfaction &Satisfaction) + : Requirement(RK_Nested, Constraint->isInstantiationDependent(), + Constraint->containsUnexpandedParameterPack(), + Satisfaction.IsSatisfied), + Constraint(Constraint), + Satisfaction(ASTConstraintSatisfaction::Create(C, Satisfaction)) {} + + NestedRequirement(StringRef InvalidConstraintEntity, + const ASTConstraintSatisfaction *Satisfaction) + : Requirement(RK_Nested, + /*IsDependent=*/false, + /*ContainsUnexpandedParameterPack*/ false, + Satisfaction->IsSatisfied), + Satisfaction(Satisfaction), HasInvalidConstraint(true), + InvalidConstraintEntity(InvalidConstraintEntity) {} + + NestedRequirement(ASTContext &C, StringRef InvalidConstraintEntity, + const ConstraintSatisfaction &Satisfaction) + : NestedRequirement(InvalidConstraintEntity, + ASTConstraintSatisfaction::Create(C, Satisfaction)) {} + + bool hasInvalidConstraint() const { return HasInvalidConstraint; } + + StringRef getInvalidConstraintEntity() { + assert(hasInvalidConstraint()); + return InvalidConstraintEntity; } Expr *getConstraintExpr() const { - assert(!isSubstitutionFailure() && "getConstraintExpr() may not be called " - "on nested requirements with " - "substitution failures."); - return Value.get<Expr *>(); + assert(!hasInvalidConstraint() && + "getConstraintExpr() may not be called " + "on nested requirements with invalid constraint."); + return Constraint; } const ASTConstraintSatisfaction &getConstraintSatisfaction() const { - assert(!isSubstitutionFailure() && "getConstraintSatisfaction() may not be " - "called on nested requirements with " - "substitution failures."); return *Satisfaction; } @@ -464,6 +490,13 @@ public: } }; +using EntityPrinter = llvm::function_ref<void(llvm::raw_ostream &)>; + +/// \brief create a Requirement::SubstitutionDiagnostic with only a +/// SubstitutedEntity and DiagLoc using Sema's allocator. +Requirement::SubstitutionDiagnostic * +createSubstDiagAt(Sema &S, SourceLocation Location, EntityPrinter Printer); + } // namespace concepts /// C++2a [expr.prim.req]: @@ -481,6 +514,8 @@ class RequiresExpr final : public Expr, unsigned NumLocalParameters; unsigned NumRequirements; RequiresExprBodyDecl *Body; + SourceLocation LParenLoc; + SourceLocation RParenLoc; SourceLocation RBraceLoc; unsigned numTrailingObjects(OverloadToken<ParmVarDecl *>) const { @@ -492,19 +527,22 @@ class RequiresExpr final : public Expr, } RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, - RequiresExprBodyDecl *Body, + RequiresExprBodyDecl *Body, SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters, + SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements, SourceLocation RBraceLoc); RequiresExpr(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters, unsigned NumRequirements); public: - static RequiresExpr * - Create(ASTContext &C, SourceLocation RequiresKWLoc, - RequiresExprBodyDecl *Body, ArrayRef<ParmVarDecl *> LocalParameters, - ArrayRef<concepts::Requirement *> Requirements, - SourceLocation RBraceLoc); + static RequiresExpr *Create(ASTContext &C, SourceLocation RequiresKWLoc, + RequiresExprBodyDecl *Body, + SourceLocation LParenLoc, + ArrayRef<ParmVarDecl *> LocalParameters, + SourceLocation RParenLoc, + ArrayRef<concepts::Requirement *> Requirements, + SourceLocation RBraceLoc); static RequiresExpr * Create(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters, unsigned NumRequirements); @@ -527,10 +565,18 @@ public: return RequiresExprBits.IsSatisfied; } + void setSatisfied(bool IsSatisfied) { + assert(!isValueDependent() && + "setSatisfied called on a dependent RequiresExpr"); + RequiresExprBits.IsSatisfied = IsSatisfied; + } + SourceLocation getRequiresKWLoc() const { return RequiresExprBits.RequiresKWLoc; } + SourceLocation getLParenLoc() const { return LParenLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } SourceLocation getRBraceLoc() const { return RBraceLoc; } static bool classof(const Stmt *T) { diff --git a/contrib/llvm-project/clang/include/clang/AST/ExprObjC.h b/contrib/llvm-project/clang/include/clang/AST/ExprObjC.h index b0f057dbaa02..f833916c91aa 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ExprObjC.h +++ b/contrib/llvm-project/clang/include/clang/AST/ExprObjC.h @@ -27,8 +27,6 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h" @@ -41,6 +39,7 @@ #include <cassert> #include <cstddef> #include <cstdint> +#include <optional> namespace clang { @@ -272,7 +271,7 @@ struct ObjCDictionaryElement { /// The number of elements this pack expansion will expand to, if /// this is a pack expansion and is known. - Optional<unsigned> NumExpansions; + std::optional<unsigned> NumExpansions; /// Determines whether this dictionary element is a pack expansion. bool isPackExpansion() const { return EllipsisLoc.isValid(); } @@ -318,6 +317,7 @@ class ObjCDictionaryLiteral final /// key/value pairs, which provide the locations of the ellipses (if /// any) and number of elements in the expansion (if known). If /// there are no pack expansions, we optimize away this storage. + LLVM_PREFERRED_TYPE(bool) unsigned HasPackExpansions : 1; SourceRange Range; @@ -362,7 +362,8 @@ public: ObjCDictionaryElement getKeyValueElement(unsigned Index) const { assert((Index < NumElements) && "Arg access out of range!"); const KeyValuePair &KV = getTrailingObjects<KeyValuePair>()[Index]; - ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(), None }; + ObjCDictionaryElement Result = {KV.Key, KV.Value, SourceLocation(), + std::nullopt}; if (HasPackExpansions) { const ExpansionData &Expansion = getTrailingObjects<ExpansionData>()[Index]; @@ -554,9 +555,11 @@ class ObjCIvarRefExpr : public Expr { SourceLocation OpLoc; // True if this is "X->F", false if this is "X.F". + LLVM_PREFERRED_TYPE(bool) bool IsArrow : 1; // True if ivar reference has no base (self assumed). + LLVM_PREFERRED_TYPE(bool) bool IsFreeIvar : 1; public: @@ -940,6 +943,23 @@ private: class ObjCMessageExpr final : public Expr, private llvm::TrailingObjects<ObjCMessageExpr, void *, SourceLocation> { +public: + /// The kind of receiver this message is sending to. + enum ReceiverKind { + /// The receiver is a class. + Class = 0, + + /// The receiver is an object instance. + Instance, + + /// The receiver is a superclass. + SuperClass, + + /// The receiver is the instance of the superclass object. + SuperInstance + }; + +private: /// Stores either the selector that this message is sending /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer /// referring to the method that we type-checked against. @@ -955,6 +975,7 @@ class ObjCMessageExpr final /// ReceiverKind values. /// /// We pad this out to a byte to avoid excessive masking and shifting. + LLVM_PREFERRED_TYPE(ReceiverKind) unsigned Kind : 8; /// Whether we have an actual method prototype in \c @@ -962,18 +983,22 @@ class ObjCMessageExpr final /// /// When non-zero, we have a method declaration; otherwise, we just /// have a selector. + LLVM_PREFERRED_TYPE(bool) unsigned HasMethod : 1; /// Whether this message send is a "delegate init call", /// i.e. a call of an init method on self from within an init method. + LLVM_PREFERRED_TYPE(bool) unsigned IsDelegateInitCall : 1; /// Whether this message send was implicitly generated by /// the implementation rather than explicitly written by the user. + LLVM_PREFERRED_TYPE(bool) unsigned IsImplicit : 1; /// Whether the locations of the selector identifiers are in a /// "standard" position, a enum SelectorLocationsKind. + LLVM_PREFERRED_TYPE(SelectorLocationsKind) unsigned SelLocsKind : 2; /// When the message expression is a send to 'super', this is @@ -1082,21 +1107,6 @@ public: friend class ASTStmtWriter; friend TrailingObjects; - /// The kind of receiver this message is sending to. - enum ReceiverKind { - /// The receiver is a class. - Class = 0, - - /// The receiver is an object instance. - Instance, - - /// The receiver is a superclass. - SuperClass, - - /// The receiver is the instance of the superclass object. - SuperInstance - }; - /// Create a message send to super. /// /// \param Context The ASTContext in which this expression will be created. @@ -1415,11 +1425,10 @@ public: SourceLocation getSelectorLoc(unsigned Index) const { assert(Index < getNumSelectorLocs() && "Index out of range!"); if (hasStandardSelLocs()) - return getStandardSelectorLoc(Index, getSelector(), - getSelLocsKind() == SelLoc_StandardWithSpace, - llvm::makeArrayRef(const_cast<Expr**>(getArgs()), - getNumArgs()), - RBracLoc); + return getStandardSelectorLoc( + Index, getSelector(), getSelLocsKind() == SelLoc_StandardWithSpace, + llvm::ArrayRef(const_cast<Expr **>(getArgs()), getNumArgs()), + RBracLoc); return getStoredSelLocs()[Index]; } @@ -1632,6 +1641,7 @@ class ObjCBridgedCastExpr final SourceLocation LParenLoc; SourceLocation BridgeKeywordLoc; + LLVM_PREFERRED_TYPE(ObjCBridgeCastKind) unsigned Kind : 2; public: @@ -1706,7 +1716,7 @@ public: /// This may be '*', in which case this should fold to true. bool hasVersion() const { return !VersionToCheck.empty(); } - VersionTuple getVersion() { return VersionToCheck; } + VersionTuple getVersion() const { return VersionToCheck; } child_range children() { return child_range(child_iterator(), child_iterator()); diff --git a/contrib/llvm-project/clang/include/clang/AST/ExprOpenMP.h b/contrib/llvm-project/clang/include/clang/AST/ExprOpenMP.h index be5dda992334..be5b1f3fdd11 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ExprOpenMP.h +++ b/contrib/llvm-project/clang/include/clang/AST/ExprOpenMP.h @@ -202,12 +202,12 @@ public: /// Fetches the dimensions for array shaping expression. ArrayRef<Expr *> getDimensions() const { - return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumDims); + return llvm::ArrayRef(getTrailingObjects<Expr *>(), NumDims); } /// Fetches source ranges for the brackets os the array shaping expression. ArrayRef<SourceRange> getBracketsRanges() const { - return llvm::makeArrayRef(getTrailingObjects<SourceRange>(), NumDims); + return llvm::ArrayRef(getTrailingObjects<SourceRange>(), NumDims); } /// Fetches base expression of array shaping expression. diff --git a/contrib/llvm-project/clang/include/clang/AST/ExternalASTMerger.h b/contrib/llvm-project/clang/include/clang/AST/ExternalASTMerger.h index 0230495a5ef3..ec4cfbe2175c 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ExternalASTMerger.h +++ b/contrib/llvm-project/clang/include/clang/AST/ExternalASTMerger.h @@ -118,7 +118,7 @@ public: /// Asks all connected ASTImporters if any of them imported the given /// declaration. If any ASTImporter did import the given declaration, /// then this function returns the declaration that D was imported from. - /// Returns nullptr if no ASTImporter did import import D. + /// Returns nullptr if no ASTImporter did import D. Decl *FindOriginalDecl(Decl *D); /// Add a set of ASTContexts as possible origins. diff --git a/contrib/llvm-project/clang/include/clang/AST/ExternalASTSource.h b/contrib/llvm-project/clang/include/clang/AST/ExternalASTSource.h index b1851afcda37..8e573965b0a3 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ExternalASTSource.h +++ b/contrib/llvm-project/clang/include/clang/AST/ExternalASTSource.h @@ -20,7 +20,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -30,6 +29,7 @@ #include <cstddef> #include <cstdint> #include <iterator> +#include <optional> #include <utility> namespace clang { @@ -160,7 +160,7 @@ public: virtual Module *getModule(unsigned ID) { return nullptr; } /// Return a descriptor for the corresponding module, if one exists. - virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID); + virtual std::optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID); enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy }; @@ -371,7 +371,7 @@ public: /// \param Source the external AST source. /// /// \returns a pointer to the AST node. - T* get(ExternalASTSource *Source) const { + T *get(ExternalASTSource *Source) const { if (isOffset()) { assert(Source && "Cannot deserialize a lazy pointer without an AST source"); @@ -379,6 +379,14 @@ public: } return reinterpret_cast<T*>(Ptr); } + + /// Retrieve the address of the AST node pointer. Deserializes the pointee if + /// necessary. + T **getAddressOfPointer(ExternalASTSource *Source) const { + // Ensure the integer is in pointer form. + (void)get(Source); + return reinterpret_cast<T**>(&Ptr); + } }; /// A lazy value (of type T) that is within an AST node of type Owner, diff --git a/contrib/llvm-project/clang/include/clang/AST/FormatString.h b/contrib/llvm-project/clang/include/clang/AST/FormatString.h index 8c944451f796..5c4ad9baaef6 100644 --- a/contrib/llvm-project/clang/include/clang/AST/FormatString.h +++ b/contrib/llvm-project/clang/include/clang/AST/FormatString.h @@ -15,10 +15,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H -#define LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H +#ifndef LLVM_CLANG_AST_FORMATSTRING_H +#define LLVM_CLANG_AST_FORMATSTRING_H #include "clang/AST/CanonicalType.h" +#include <optional> namespace clang { @@ -127,8 +128,12 @@ public: dArg, DArg, // Apple extension iArg, + // C23 conversion specifiers. + bArg, + BArg, + IntArgBeg = dArg, - IntArgEnd = iArg, + IntArgEnd = BArg, oArg, OArg, // Apple extension @@ -237,7 +242,7 @@ public: bool isPrintfKind() const { return IsPrintf; } - Optional<ConversionSpecifier> getStandardSpecifier() const; + std::optional<ConversionSpecifier> getStandardSpecifier() const; protected: bool IsPrintf; @@ -257,8 +262,14 @@ public: /// instance, "%d" and float. NoMatch = 0, /// The conversion specifier and the argument type are compatible. For - /// instance, "%d" and _Bool. + /// instance, "%d" and int. Match = 1, + /// The conversion specifier and the argument type are compatible because of + /// default argument promotions. For instance, "%hhd" and int. + MatchPromotion, + /// The conversion specifier and the argument type are compatible but still + /// seems likely to be an error. For instanace, "%hhd" and short. + NoMatchPromotionTypeConfusion, /// The conversion specifier and the argument type are disallowed by the C /// standard, but are in practice harmless. For instance, "%p" and int*. NoMatchPedantic, @@ -332,11 +343,11 @@ public: unsigned amountLength, bool usesPositionalArg) : start(amountStart), length(amountLength), hs(howSpecified), amt(amount), - UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {} + UsesPositionalArg(usesPositionalArg), UsesDotPrefix(false) {} OptionalAmount(bool valid = true) : start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0), - UsesPositionalArg(0), UsesDotPrefix(0) {} + UsesPositionalArg(false), UsesDotPrefix(false) {} explicit OptionalAmount(unsigned Amount) : start(nullptr), length(0), hs(Constant), amt(Amount), @@ -456,7 +467,7 @@ public: bool hasStandardLengthModifier() const; - Optional<LengthModifier> getCorrectedLengthModifier() const; + std::optional<LengthModifier> getCorrectedLengthModifier() const; bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const; @@ -726,7 +737,8 @@ public: virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, - unsigned specifierLen) { + unsigned specifierLen, + const TargetInfo &Target) { return true; } diff --git a/contrib/llvm-project/clang/include/clang/AST/GlobalDecl.h b/contrib/llvm-project/clang/include/clang/AST/GlobalDecl.h index 8cb56fb4ae90..88abba28c991 100644 --- a/contrib/llvm-project/clang/include/clang/AST/GlobalDecl.h +++ b/contrib/llvm-project/clang/include/clang/AST/GlobalDecl.h @@ -18,6 +18,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclOpenMP.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Basic/ABI.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMapInfo.h" @@ -129,8 +130,12 @@ public: } KernelReferenceKind getKernelReferenceKind() const { - assert(isa<FunctionDecl>(getDecl()) && - cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() && + assert(((isa<FunctionDecl>(getDecl()) && + cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>()) || + (isa<FunctionTemplateDecl>(getDecl()) && + cast<FunctionTemplateDecl>(getDecl()) + ->getTemplatedDecl() + ->hasAttr<CUDAGlobalAttr>())) && "Decl is not a GPU kernel!"); return static_cast<KernelReferenceKind>(Value.getInt()); } diff --git a/contrib/llvm-project/clang/include/clang/AST/IgnoreExpr.h b/contrib/llvm-project/clang/include/clang/AST/IgnoreExpr.h index a7e9b07bef6c..917bada61fa6 100644 --- a/contrib/llvm-project/clang/include/clang/AST/IgnoreExpr.h +++ b/contrib/llvm-project/clang/include/clang/AST/IgnoreExpr.h @@ -23,7 +23,8 @@ namespace detail { inline Expr *IgnoreExprNodesImpl(Expr *E) { return E; } template <typename FnTy, typename... FnTys> Expr *IgnoreExprNodesImpl(Expr *E, FnTy &&Fn, FnTys &&... Fns) { - return IgnoreExprNodesImpl(Fn(E), std::forward<FnTys>(Fns)...); + return IgnoreExprNodesImpl(std::forward<FnTy>(Fn)(E), + std::forward<FnTys>(Fns)...); } } // namespace detail @@ -165,6 +166,11 @@ inline Expr *IgnoreParensSingleStep(Expr *E) { return CE->getChosenSubExpr(); } + else if (auto *PE = dyn_cast<PredefinedExpr>(E)) { + if (PE->isTransparent() && PE->getFunctionName()) + return PE->getFunctionName(); + } + return E; } diff --git a/contrib/llvm-project/clang/include/clang/AST/JSONNodeDumper.h b/contrib/llvm-project/clang/include/clang/AST/JSONNodeDumper.h index a96e21993e20..4def5389137f 100644 --- a/contrib/llvm-project/clang/include/clang/AST/JSONNodeDumper.h +++ b/contrib/llvm-project/clang/include/clang/AST/JSONNodeDumper.h @@ -1,9 +1,8 @@ //===--- JSONNodeDumper.h - Printing of AST nodes to JSON -----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -161,6 +160,7 @@ class JSONNodeDumper std::string createPointerRepresentation(const void *Ptr); llvm::json::Object createQualType(QualType QT, bool Desugar = true); llvm::json::Object createBareDeclRef(const Decl *D); + llvm::json::Object createFPOptions(FPOptionsOverride FPO); void writeBareDeclRef(const Decl *D); llvm::json::Object createCXXRecordDefinitionData(const CXXRecordDecl *RD); llvm::json::Object createCXXBaseSpecifier(const CXXBaseSpecifier &BS); @@ -208,7 +208,16 @@ public: void Visit(const concepts::Requirement *R); void Visit(const APValue &Value, QualType Ty); + void VisitAliasAttr(const AliasAttr *AA); + void VisitCleanupAttr(const CleanupAttr *CA); + void VisitDeprecatedAttr(const DeprecatedAttr *DA); + void VisitUnavailableAttr(const UnavailableAttr *UA); + void VisitSectionAttr(const SectionAttr *SA); + void VisitVisibilityAttr(const VisibilityAttr *VA); + void VisitTLSModelAttr(const TLSModelAttr *TA); + void VisitTypedefType(const TypedefType *TT); + void VisitUsingType(const UsingType *TT); void VisitFunctionType(const FunctionType *T); void VisitFunctionProtoType(const FunctionProtoType *T); void VisitRValueReferenceType(const ReferenceType *RT); @@ -220,6 +229,9 @@ public: void VisitUnaryTransformType(const UnaryTransformType *UTT); void VisitTagType(const TagType *TT); void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT); + void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT); + void + VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T); void VisitAutoType(const AutoType *AT); void VisitTemplateSpecializationType(const TemplateSpecializationType *TST); void VisitInjectedClassNameType(const InjectedClassNameType *ICNT); @@ -245,6 +257,7 @@ public: void VisitEnumConstantDecl(const EnumConstantDecl *ECD); void VisitRecordDecl(const RecordDecl *RD); void VisitCXXRecordDecl(const CXXRecordDecl *RD); + void VisitHLSLBufferDecl(const HLSLBufferDecl *D); void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); @@ -272,6 +285,7 @@ public: void VisitBinaryOperator(const BinaryOperator *BO); void VisitCompoundAssignOperator(const CompoundAssignOperator *CAO); void VisitMemberExpr(const MemberExpr *ME); + void VisitAtomicExpr(const AtomicExpr *AE); void VisitCXXNewExpr(const CXXNewExpr *NE); void VisitCXXDeleteExpr(const CXXDeleteExpr *DE); void VisitCXXThisExpr(const CXXThisExpr *TE); @@ -318,6 +332,7 @@ public: void VisitGotoStmt(const GotoStmt *GS); void VisitWhileStmt(const WhileStmt *WS); void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *OACS); + void VisitCompoundStmt(const CompoundStmt *IS); void VisitNullTemplateArgument(const TemplateArgument &TA); void VisitTypeTemplateArgument(const TemplateArgument &TA); @@ -379,7 +394,7 @@ class JSONDumper : public ASTNodeTraverser<JSONDumper, JSONNodeDumper> { case TSK_ExplicitInstantiationDefinition: if (!DumpExplicitInst) break; - LLVM_FALLTHROUGH; + [[fallthrough]]; case TSK_Undeclared: case TSK_ImplicitInstantiation: if (DumpRefOnly) diff --git a/contrib/llvm-project/clang/include/clang/AST/LambdaCapture.h b/contrib/llvm-project/clang/include/clang/AST/LambdaCapture.h index 8e2806545dd6..62e7716ed369 100644 --- a/contrib/llvm-project/clang/include/clang/AST/LambdaCapture.h +++ b/contrib/llvm-project/clang/include/clang/AST/LambdaCapture.h @@ -71,7 +71,7 @@ public: /// capture that is a pack expansion, or an invalid source /// location to indicate that this is not a pack expansion. LambdaCapture(SourceLocation Loc, bool Implicit, LambdaCaptureKind Kind, - VarDecl *Var = nullptr, + ValueDecl *Var = nullptr, SourceLocation EllipsisLoc = SourceLocation()); /// Determine the kind of capture. @@ -86,7 +86,7 @@ public: /// Determine whether this capture handles a variable. bool capturesVariable() const { - return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer()); + return isa_and_nonnull<ValueDecl>(DeclAndBits.getPointer()); } /// Determine whether this captures a variable length array bound @@ -101,9 +101,9 @@ public: /// /// This operation is only valid if this capture is a variable capture /// (other than a capture of \c this). - VarDecl *getCapturedVar() const { + ValueDecl *getCapturedVar() const { assert(capturesVariable() && "No variable available for capture"); - return static_cast<VarDecl *>(DeclAndBits.getPointer()); + return static_cast<ValueDecl *>(DeclAndBits.getPointer()); } /// Determine whether this was an implicit capture (not diff --git a/contrib/llvm-project/clang/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h b/contrib/llvm-project/clang/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h index e42f0449f6db..054220b8a32c 100644 --- a/contrib/llvm-project/clang/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h +++ b/contrib/llvm-project/clang/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_LEXICALLY_ORDERED_RECURSIVEASTVISITOR_H -#define LLVM_CLANG_AST_LEXICALLY_ORDERED_RECURSIVEASTVISITOR_H +#ifndef LLVM_CLANG_AST_LEXICALLYORDEREDRECURSIVEASTVISITOR_H +#define LLVM_CLANG_AST_LEXICALLYORDEREDRECURSIVEASTVISITOR_H #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/LLVM.h" @@ -160,4 +160,4 @@ private: } // end namespace clang -#endif // LLVM_CLANG_AST_LEXICALLY_ORDERED_RECURSIVEASTVISITOR_H +#endif // LLVM_CLANG_AST_LEXICALLYORDEREDRECURSIVEASTVISITOR_H diff --git a/contrib/llvm-project/clang/include/clang/AST/LocInfoType.h b/contrib/llvm-project/clang/include/clang/AST/LocInfoType.h index 7e845ad03587..876c7deeceb9 100644 --- a/contrib/llvm-project/clang/include/clang/AST/LocInfoType.h +++ b/contrib/llvm-project/clang/include/clang/AST/LocInfoType.h @@ -10,8 +10,8 @@ // source-location information. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_LOCINFOTYPE_H -#define LLVM_CLANG_SEMA_LOCINFOTYPE_H +#ifndef LLVM_CLANG_AST_LOCINFOTYPE_H +#define LLVM_CLANG_AST_LOCINFOTYPE_H #include "clang/AST/Type.h" @@ -54,4 +54,4 @@ public: } // end namespace clang -#endif // LLVM_CLANG_SEMA_LOCINFOTYPE_H +#endif // LLVM_CLANG_AST_LOCINFOTYPE_H diff --git a/contrib/llvm-project/clang/include/clang/AST/Mangle.h b/contrib/llvm-project/clang/include/clang/AST/Mangle.h index 7d02f08e0120..e586b0cec43d 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Mangle.h +++ b/contrib/llvm-project/clang/include/clang/AST/Mangle.h @@ -19,6 +19,7 @@ #include "clang/Basic/ABI.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Casting.h" +#include <optional> namespace llvm { class raw_ostream; @@ -54,18 +55,23 @@ private: ASTContext &Context; DiagnosticsEngine &Diags; const ManglerKind Kind; + /// For aux target. If true, uses mangling number for aux target from + /// ASTContext. + bool IsAux = false; llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds; llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds; llvm::DenseMap<const NamedDecl*, uint64_t> AnonStructIds; + llvm::DenseMap<const FunctionDecl*, unsigned> FuncAnonStructSize; public: ManglerKind getKind() const { return Kind; } - explicit MangleContext(ASTContext &Context, - DiagnosticsEngine &Diags, - ManglerKind Kind) - : Context(Context), Diags(Diags), Kind(Kind) {} + bool isAux() const { return IsAux; } + + explicit MangleContext(ASTContext &Context, DiagnosticsEngine &Diags, + ManglerKind Kind, bool IsAux = false) + : Context(Context), Diags(Diags), Kind(Kind), IsAux(IsAux) {} virtual ~MangleContext() { } @@ -83,9 +89,17 @@ public: return Result.first->second; } - uint64_t getAnonymousStructId(const NamedDecl *D) { + uint64_t getAnonymousStructId(const NamedDecl *D, + const FunctionDecl *FD = nullptr) { + auto FindResult = AnonStructIds.find(D); + if (FindResult != AnonStructIds.end()) + return FindResult->second; + + // If FunctionDecl is passed in, the anonymous structID will be per-function + // based. + unsigned Id = FD ? FuncAnonStructSize[FD]++ : AnonStructIds.size(); std::pair<llvm::DenseMap<const NamedDecl *, uint64_t>::iterator, bool> - Result = AnonStructIds.insert(std::make_pair(D, AnonStructIds.size())); + Result = AnonStructIds.insert(std::make_pair(D, Id)); return Result.first->second; } @@ -126,7 +140,8 @@ public: unsigned ManglingNumber, raw_ostream &) = 0; virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0; - virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0; + virtual void mangleCXXRTTIName(QualType T, raw_ostream &, + bool NormalizeIntegers = false) = 0; virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0; virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream&); @@ -153,17 +168,18 @@ public: virtual void mangleDynamicAtExitDestructor(const VarDecl *D, raw_ostream &) = 0; - virtual void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl, + virtual void mangleSEHFilterExpression(GlobalDecl EnclosingDecl, raw_ostream &Out) = 0; - virtual void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl, + virtual void mangleSEHFinallyBlock(GlobalDecl EnclosingDecl, raw_ostream &Out) = 0; /// Generates a unique string for an externally visible type for use with TBAA /// or type uniquing. /// TODO: Extend this to internal types by generating names that are unique /// across translation units so it can be used with LTO. - virtual void mangleTypeName(QualType T, raw_ostream &) = 0; + virtual void mangleCanonicalTypeName(QualType T, raw_ostream &, + bool NormalizeIntegers = false) = 0; /// @} }; @@ -171,9 +187,10 @@ public: class ItaniumMangleContext : public MangleContext { public: using DiscriminatorOverrideTy = - llvm::Optional<unsigned> (*)(ASTContext &, const NamedDecl *); - explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D) - : MangleContext(C, D, MK_Itanium) {} + std::optional<unsigned> (*)(ASTContext &, const NamedDecl *); + explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D, + bool IsAux = false) + : MangleContext(C, D, MK_Itanium, IsAux) {} virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0; virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0; @@ -194,6 +211,8 @@ public: virtual void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &) = 0; + virtual void mangleModuleInitializer(const Module *Module, raw_ostream &) = 0; + // This has to live here, otherwise the CXXNameMangler won't have access to // it. virtual DiscriminatorOverrideTy getDiscriminatorOverride() const = 0; @@ -201,17 +220,19 @@ public: return C->getKind() == MK_Itanium; } - static ItaniumMangleContext *create(ASTContext &Context, - DiagnosticsEngine &Diags); + static ItaniumMangleContext * + create(ASTContext &Context, DiagnosticsEngine &Diags, bool IsAux = false); static ItaniumMangleContext *create(ASTContext &Context, DiagnosticsEngine &Diags, - DiscriminatorOverrideTy Discriminator); + DiscriminatorOverrideTy Discriminator, + bool IsAux = false); }; class MicrosoftMangleContext : public MangleContext { public: - explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D) - : MangleContext(C, D, MK_Microsoft) {} + explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D, + bool IsAux = false) + : MangleContext(C, D, MK_Microsoft, IsAux) {} /// Mangle vftable symbols. Only a subset of the bases along the path /// to the vftable are included in the name. It's up to the caller to pick @@ -270,8 +291,8 @@ public: return C->getKind() == MK_Microsoft; } - static MicrosoftMangleContext *create(ASTContext &Context, - DiagnosticsEngine &Diags); + static MicrosoftMangleContext * + create(ASTContext &Context, DiagnosticsEngine &Diags, bool IsAux = false); }; class ASTNameGenerator { diff --git a/contrib/llvm-project/clang/include/clang/AST/MangleNumberingContext.h b/contrib/llvm-project/clang/include/clang/AST/MangleNumberingContext.h index eb33759682d6..1313c94eb122 100644 --- a/contrib/llvm-project/clang/include/clang/AST/MangleNumberingContext.h +++ b/contrib/llvm-project/clang/include/clang/AST/MangleNumberingContext.h @@ -21,14 +21,15 @@ namespace clang { class BlockDecl; class CXXMethodDecl; -class IdentifierInfo; class TagDecl; -class Type; class VarDecl; /// Keeps track of the mangled names of lambda expressions and block /// literals within a particular context. class MangleNumberingContext { + // The index of the next lambda we encounter in this context. + unsigned LambdaIndex = 0; + public: virtual ~MangleNumberingContext() {} @@ -57,6 +58,11 @@ public: /// given call operator within the device context. No device number is /// assigned if there's no device numbering context is associated. virtual unsigned getDeviceManglingNumber(const CXXMethodDecl *) { return 0; } + + // Retrieve the index of the next lambda appearing in this context, which is + // used for deduplicating lambdas across modules. Note that this is a simple + // sequence number and is not ABI-dependent. + unsigned getNextLambdaIndex() { return LambdaIndex++; } }; } // end namespace clang diff --git a/contrib/llvm-project/clang/include/clang/AST/NSAPI.h b/contrib/llvm-project/clang/include/clang/AST/NSAPI.h index a8bd2d0f17e6..d411c34191ed 100644 --- a/contrib/llvm-project/clang/include/clang/AST/NSAPI.h +++ b/contrib/llvm-project/clang/include/clang/AST/NSAPI.h @@ -11,7 +11,7 @@ #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" +#include <optional> namespace clang { class ASTContext; @@ -89,7 +89,7 @@ public: Selector getNSArraySelector(NSArrayMethodKind MK) const; /// Return NSArrayMethodKind if \p Sel is such a selector. - Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel); + std::optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel); /// Enumerates the NSDictionary/NSMutableDictionary methods used /// to generate literals and to apply some checks. @@ -114,7 +114,7 @@ public: Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const; /// Return NSDictionaryMethodKind if \p Sel is such a selector. - Optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel); + std::optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel); /// Enumerates the NSMutableSet/NSOrderedSet methods used /// to apply some checks. @@ -131,7 +131,7 @@ public: Selector getNSSetSelector(NSSetMethodKind MK) const; /// Return NSSetMethodKind if \p Sel is such a selector. - Optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel); + std::optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel); /// Returns selector for "objectForKeyedSubscript:". Selector getObjectForKeyedSubscriptSelector() const { @@ -203,13 +203,13 @@ public: } /// Return NSNumberLiteralMethodKind if \p Sel is such a selector. - Optional<NSNumberLiteralMethodKind> - getNSNumberLiteralMethodKind(Selector Sel) const; + std::optional<NSNumberLiteralMethodKind> + getNSNumberLiteralMethodKind(Selector Sel) const; /// Determine the appropriate NSNumber factory method kind for a /// literal of the given type. - Optional<NSNumberLiteralMethodKind> - getNSNumberFactoryMethodKind(QualType T) const; + std::optional<NSNumberLiteralMethodKind> + getNSNumberFactoryMethodKind(QualType T) const; /// Returns true if \param T is a typedef of "BOOL" in objective-c. bool isObjCBOOLType(QualType T) const; diff --git a/contrib/llvm-project/clang/include/clang/AST/NestedNameSpecifier.h b/contrib/llvm-project/clang/include/clang/AST/NestedNameSpecifier.h index 8bc3e25c0f4b..3b6cf9721185 100644 --- a/contrib/llvm-project/clang/include/clang/AST/NestedNameSpecifier.h +++ b/contrib/llvm-project/clang/include/clang/AST/NestedNameSpecifier.h @@ -162,7 +162,7 @@ public: /// Return the prefix of this nested name specifier. /// /// The prefix contains all of the parts of the nested name - /// specifier that preced this current specifier. For example, for a + /// specifier that precede this current specifier. For example, for a /// nested name specifier that represents "foo::bar::", the current /// specifier will contain "bar::" and the prefix will contain /// "foo::". @@ -521,7 +521,7 @@ public: /// NestedNameSpecifiers into a diagnostic with <<. inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, NestedNameSpecifier *NNS) { - DB.AddTaggedVal(reinterpret_cast<intptr_t>(NNS), + DB.AddTaggedVal(reinterpret_cast<uint64_t>(NNS), DiagnosticsEngine::ak_nestednamespec); return DB; } diff --git a/contrib/llvm-project/clang/include/clang/AST/NonTrivialTypeVisitor.h b/contrib/llvm-project/clang/include/clang/AST/NonTrivialTypeVisitor.h index c95516538ad1..cf320c8a478a 100644 --- a/contrib/llvm-project/clang/include/clang/AST/NonTrivialTypeVisitor.h +++ b/contrib/llvm-project/clang/include/clang/AST/NonTrivialTypeVisitor.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_NON_TRIVIAL_TYPE_VISITOR_H -#define LLVM_CLANG_NON_TRIVIAL_TYPE_VISITOR_H +#ifndef LLVM_CLANG_AST_NONTRIVIALTYPEVISITOR_H +#define LLVM_CLANG_AST_NONTRIVIALTYPEVISITOR_H #include "clang/AST/Type.h" diff --git a/contrib/llvm-project/clang/include/clang/AST/ODRDiagsEmitter.h b/contrib/llvm-project/clang/include/clang/AST/ODRDiagsEmitter.h new file mode 100644 index 000000000000..1f7faaa06e54 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/AST/ODRDiagsEmitter.h @@ -0,0 +1,203 @@ +//===- ODRDiagsEmitter.h - Emits diagnostic for ODR mismatches --*- 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_AST_ODRDIAGSEMITTER_H +#define LLVM_CLANG_AST_ODRDIAGSEMITTER_H + +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LangOptions.h" + +namespace clang { + +class ODRDiagsEmitter { +public: + ODRDiagsEmitter(DiagnosticsEngine &Diags, const ASTContext &Context, + const LangOptions &LangOpts) + : Diags(Diags), Context(Context), LangOpts(LangOpts) {} + + /// Diagnose ODR mismatch between 2 FunctionDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseMismatch(const FunctionDecl *FirstFunction, + const FunctionDecl *SecondFunction) const; + + /// Diagnose ODR mismatch between 2 EnumDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseMismatch(const EnumDecl *FirstEnum, + const EnumDecl *SecondEnum) const; + + /// Diagnose ODR mismatch between 2 CXXRecordDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + /// To compare 2 declarations with merged and identical definition data + /// you need to provide pre-merge definition data in \p SecondDD. + bool + diagnoseMismatch(const CXXRecordDecl *FirstRecord, + const CXXRecordDecl *SecondRecord, + const struct CXXRecordDecl::DefinitionData *SecondDD) const; + + /// Diagnose ODR mismatch between 2 RecordDecl that are not CXXRecordDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseMismatch(const RecordDecl *FirstRecord, + const RecordDecl *SecondRecord) const; + + /// Diagnose ODR mismatch between 2 ObjCInterfaceDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseMismatch( + const ObjCInterfaceDecl *FirstID, const ObjCInterfaceDecl *SecondID, + const struct ObjCInterfaceDecl::DefinitionData *SecondDD) const; + + /// Diagnose ODR mismatch between ObjCInterfaceDecl with different + /// definitions. + bool diagnoseMismatch(const ObjCInterfaceDecl *FirstID, + const ObjCInterfaceDecl *SecondID) const { + assert(FirstID->data().Definition != SecondID->data().Definition && + "Don't diagnose differences when definitions are merged already"); + return diagnoseMismatch(FirstID, SecondID, &SecondID->data()); + } + + /// Diagnose ODR mismatch between 2 ObjCProtocolDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + /// To compare 2 declarations with merged and identical definition data + /// you need to provide pre-merge definition data in \p SecondDD. + bool diagnoseMismatch( + const ObjCProtocolDecl *FirstProtocol, + const ObjCProtocolDecl *SecondProtocol, + const struct ObjCProtocolDecl::DefinitionData *SecondDD) const; + + /// Diagnose ODR mismatch between ObjCProtocolDecl with different definitions. + bool diagnoseMismatch(const ObjCProtocolDecl *FirstProtocol, + const ObjCProtocolDecl *SecondProtocol) const { + assert(FirstProtocol->data().Definition != + SecondProtocol->data().Definition && + "Don't diagnose differences when definitions are merged already"); + return diagnoseMismatch(FirstProtocol, SecondProtocol, + &SecondProtocol->data()); + } + + /// Get the best name we know for the module that owns the given + /// declaration, or an empty string if the declaration is not from a module. + static std::string getOwningModuleNameForDiagnostic(const Decl *D); + +private: + using DeclHashes = llvm::SmallVector<std::pair<const Decl *, unsigned>, 4>; + + // Used with err_module_odr_violation_mismatch_decl, + // note_module_odr_violation_mismatch_decl, + // err_module_odr_violation_mismatch_decl_unknown, + // and note_module_odr_violation_mismatch_decl_unknown + // This list should be the same Decl's as in ODRHash::isSubDeclToBeProcessed + enum ODRMismatchDecl { + EndOfClass, + PublicSpecifer, + PrivateSpecifer, + ProtectedSpecifer, + StaticAssert, + Field, + CXXMethod, + TypeAlias, + TypeDef, + Var, + Friend, + FunctionTemplate, + ObjCMethod, + ObjCIvar, + ObjCProperty, + Other + }; + + struct DiffResult { + const Decl *FirstDecl = nullptr, *SecondDecl = nullptr; + ODRMismatchDecl FirstDiffType = Other, SecondDiffType = Other; + }; + + // If there is a diagnoseable difference, FirstDiffType and + // SecondDiffType will not be Other and FirstDecl and SecondDecl will be + // filled in if not EndOfClass. + static DiffResult FindTypeDiffs(DeclHashes &FirstHashes, + DeclHashes &SecondHashes); + + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const { + return Diags.Report(Loc, DiagID); + } + + // Use this to diagnose that an unexpected Decl was encountered + // or no difference was detected. This causes a generic error + // message to be emitted. + void diagnoseSubMismatchUnexpected(DiffResult &DR, + const NamedDecl *FirstRecord, + StringRef FirstModule, + const NamedDecl *SecondRecord, + StringRef SecondModule) const; + + void diagnoseSubMismatchDifferentDeclKinds(DiffResult &DR, + const NamedDecl *FirstRecord, + StringRef FirstModule, + const NamedDecl *SecondRecord, + StringRef SecondModule) const; + + bool diagnoseSubMismatchField(const NamedDecl *FirstRecord, + StringRef FirstModule, StringRef SecondModule, + const FieldDecl *FirstField, + const FieldDecl *SecondField) const; + + bool diagnoseSubMismatchTypedef(const NamedDecl *FirstRecord, + StringRef FirstModule, StringRef SecondModule, + const TypedefNameDecl *FirstTD, + const TypedefNameDecl *SecondTD, + bool IsTypeAlias) const; + + bool diagnoseSubMismatchVar(const NamedDecl *FirstRecord, + StringRef FirstModule, StringRef SecondModule, + const VarDecl *FirstVD, + const VarDecl *SecondVD) const; + + /// Check if protocol lists are the same and diagnose if they are different. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseSubMismatchProtocols(const ObjCProtocolList &FirstProtocols, + const ObjCContainerDecl *FirstContainer, + StringRef FirstModule, + const ObjCProtocolList &SecondProtocols, + const ObjCContainerDecl *SecondContainer, + StringRef SecondModule) const; + + /// Check if Objective-C methods are the same and diagnose if different. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseSubMismatchObjCMethod(const NamedDecl *FirstObjCContainer, + StringRef FirstModule, + StringRef SecondModule, + const ObjCMethodDecl *FirstMethod, + const ObjCMethodDecl *SecondMethod) const; + + /// Check if Objective-C properties are the same and diagnose if different. + /// + /// Returns true if found a mismatch and diagnosed it. + bool + diagnoseSubMismatchObjCProperty(const NamedDecl *FirstObjCContainer, + StringRef FirstModule, StringRef SecondModule, + const ObjCPropertyDecl *FirstProp, + const ObjCPropertyDecl *SecondProp) const; + +private: + DiagnosticsEngine &Diags; + const ASTContext &Context; + const LangOptions &LangOpts; +}; + +} // namespace clang + +#endif diff --git a/contrib/llvm-project/clang/include/clang/AST/ODRHash.h b/contrib/llvm-project/clang/include/clang/AST/ODRHash.h index 2e8593e0b835..a1caa6d39a87 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ODRHash.h +++ b/contrib/llvm-project/clang/include/clang/AST/ODRHash.h @@ -25,6 +25,7 @@ namespace clang { +class APValue; class Decl; class IdentifierInfo; class NestedNameSpecifier; @@ -55,6 +56,14 @@ public: // more information than the AddDecl class. void AddCXXRecordDecl(const CXXRecordDecl *Record); + // Use this for ODR checking records in C/Objective-C between modules. This + // method compares more information than the AddDecl class. + void AddRecordDecl(const RecordDecl *Record); + + // Use this for ODR checking ObjC interfaces. This + // method compares more information than the AddDecl class. + void AddObjCInterfaceDecl(const ObjCInterfaceDecl *Record); + // Use this for ODR checking functions between modules. This method compares // more information than the AddDecl class. SkipBody will process the // hash as if the function has no body. @@ -64,6 +73,10 @@ public: // more information than the AddDecl class. void AddEnumDecl(const EnumDecl *Enum); + // Use this for ODR checking ObjC protocols. This + // method compares more information than the AddDecl class. + void AddObjCProtocolDecl(const ObjCProtocolDecl *P); + // Process SubDecls of the main Decl. This method calls the DeclVisitor // while AddDecl does not. void AddSubDecl(const Decl *D); @@ -89,7 +102,9 @@ public: // Save booleans until the end to lower the size of data to process. void AddBoolean(bool value); - static bool isDeclToBeProcessed(const Decl* D, const DeclContext *Parent); + void AddStructuralValue(const APValue &); + + static bool isSubDeclToBeProcessed(const Decl *D, const DeclContext *Parent); private: void AddDeclarationNameImpl(DeclarationName Name); diff --git a/contrib/llvm-project/clang/include/clang/AST/OSLog.h b/contrib/llvm-project/clang/include/clang/AST/OSLog.h index c24e79ce6da0..3772597e2616 100644 --- a/contrib/llvm-project/clang/include/clang/AST/OSLog.h +++ b/contrib/llvm-project/clang/include/clang/AST/OSLog.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H -#define LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H +#ifndef LLVM_CLANG_AST_OSLOG_H +#define LLVM_CLANG_AST_OSLOG_H #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" diff --git a/contrib/llvm-project/clang/include/clang/AST/OpenMPClause.h b/contrib/llvm-project/clang/include/clang/AST/OpenMPClause.h index aaddcfa307da..924ca189381b 100644 --- a/contrib/llvm-project/clang/include/clang/AST/OpenMPClause.h +++ b/contrib/llvm-project/clang/include/clang/AST/OpenMPClause.h @@ -32,6 +32,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/Frontend/OpenMP/OMPAssume.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" #include "llvm/Frontend/OpenMP/OMPContext.h" #include "llvm/Support/Casting.h" @@ -106,6 +107,89 @@ public: static bool classof(const OMPClause *) { return true; } }; +template <OpenMPClauseKind ClauseKind> +struct OMPNoChildClause : public OMPClause { + /// Build '\p ClauseKind' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + OMPNoChildClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(ClauseKind, StartLoc, EndLoc) {} + + /// Build an empty clause. + OMPNoChildClause() + : OMPClause(ClauseKind, SourceLocation(), SourceLocation()) {} + + 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()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == ClauseKind; + } +}; + +template <OpenMPClauseKind ClauseKind, class Base> +class OMPOneStmtClause : public Base { + + /// Location of '('. + SourceLocation LParenLoc; + + /// Sub-expression. + Stmt *S = nullptr; + +protected: + void setStmt(Stmt *S) { this->S = S; } + +public: + OMPOneStmtClause(Stmt *S, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : Base(ClauseKind, StartLoc, EndLoc), LParenLoc(LParenLoc), S(S) {} + + OMPOneStmtClause() : Base(ClauseKind, SourceLocation(), SourceLocation()) {} + + /// Return the associated statement, potentially casted to \p T. + template <typename T> T *getStmtAs() const { return cast_or_null<T>(S); } + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + + /// Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + using child_iterator = StmtIterator; + using const_child_iterator = ConstStmtIterator; + using child_range = llvm::iterator_range<child_iterator>; + using const_child_range = llvm::iterator_range<const_child_iterator>; + + child_range children() { return child_range(&S, &S + 1); } + + const_child_range children() const { return const_child_range(&S, &S + 1); } + + // TODO: Consider making the getAddrOfExprAsWritten version the default. + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == ClauseKind; + } +}; + /// Class that handles pre-initialization statement for some clauses, like /// 'shedule', 'firstprivate' etc. class OMPClauseWithPreInit { @@ -252,7 +336,7 @@ public: /// Fetches list of all variables in the clause. ArrayRef<const Expr *> getVarRefs() const { - return llvm::makeArrayRef( + return llvm::ArrayRef( static_cast<const T *>(this)->template getTrailingObjects<Expr *>(), NumVars); } @@ -266,17 +350,12 @@ public: /// \endcode /// In this example directive '#pragma omp allocate' has simple 'allocator' /// clause with the allocator 'omp_default_mem_alloc'. -class OMPAllocatorClause : public OMPClause { +class OMPAllocatorClause final + : public OMPOneStmtClause<llvm::omp::OMPC_allocator, OMPClause> { friend class OMPClauseReader; - /// Location of '('. - SourceLocation LParenLoc; - - /// Expression with the allocator. - Stmt *Allocator = nullptr; - /// Set allocator. - void setAllocator(Expr *A) { Allocator = A; } + void setAllocator(Expr *A) { setStmt(A); } public: /// Build 'allocator' clause with the given allocator. @@ -287,39 +366,58 @@ public: /// \param EndLoc Ending location of the clause. OMPAllocatorClause(Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(llvm::omp::OMPC_allocator, StartLoc, EndLoc), - LParenLoc(LParenLoc), Allocator(A) {} + : OMPOneStmtClause(A, StartLoc, LParenLoc, EndLoc) {} /// Build an empty clause. - OMPAllocatorClause() - : OMPClause(llvm::omp::OMPC_allocator, SourceLocation(), - SourceLocation()) {} + OMPAllocatorClause() : OMPOneStmtClause() {} - /// Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// Returns allocator. + Expr *getAllocator() const { return getStmtAs<Expr>(); } +}; - /// Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } +/// This represents the 'align' clause in the '#pragma omp allocate' +/// directive. +/// +/// \code +/// #pragma omp allocate(a) allocator(omp_default_mem_alloc) align(8) +/// \endcode +/// In this example directive '#pragma omp allocate' has simple 'allocator' +/// clause with the allocator 'omp_default_mem_alloc' and align clause with +/// value of 8. +class OMPAlignClause final + : public OMPOneStmtClause<llvm::omp::OMPC_align, OMPClause> { + friend class OMPClauseReader; - /// Returns allocator. - Expr *getAllocator() const { return cast_or_null<Expr>(Allocator); } + /// Set alignment value. + void setAlignment(Expr *A) { setStmt(A); } - child_range children() { return child_range(&Allocator, &Allocator + 1); } + /// Build 'align' clause with the given alignment + /// + /// \param A Alignment value. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + OMPAlignClause(Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPOneStmtClause(A, StartLoc, LParenLoc, EndLoc) {} - const_child_range children() const { - return const_child_range(&Allocator, &Allocator + 1); - } + /// Build an empty clause. + OMPAlignClause() : OMPOneStmtClause() {} - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } +public: + /// Build 'align' clause with the given alignment + /// + /// \param A Alignment value. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + static OMPAlignClause *Create(const ASTContext &C, Expr *A, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_allocator; - } + /// Returns alignment + Expr *getAlignment() const { return getStmtAs<Expr>(); } }; /// This represents clause 'allocate' in the '#pragma omp ...' directives. @@ -527,17 +625,13 @@ public: /// \endcode /// In this example directive '#pragma omp task' has simple 'final' /// clause with condition 'a > 5'. -class OMPFinalClause : public OMPClause, public OMPClauseWithPreInit { +class OMPFinalClause final + : public OMPOneStmtClause<llvm::omp::OMPC_final, OMPClause>, + public OMPClauseWithPreInit { friend class OMPClauseReader; - /// Location of '('. - SourceLocation LParenLoc; - - /// Condition of the 'if' clause. - Stmt *Condition = nullptr; - /// Set condition. - void setCondition(Expr *Cond) { Condition = Cond; } + void setCondition(Expr *Cond) { setStmt(Cond); } public: /// Build 'final' clause with condition \a Cond. @@ -552,42 +646,23 @@ public: OMPFinalClause(Expr *Cond, Stmt *HelperCond, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(llvm::omp::OMPC_final, StartLoc, EndLoc), - OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Condition(Cond) { + : OMPOneStmtClause(Cond, StartLoc, LParenLoc, EndLoc), + OMPClauseWithPreInit(this) { setPreInitStmt(HelperCond, CaptureRegion); } /// Build an empty clause. - OMPFinalClause() - : OMPClause(llvm::omp::OMPC_final, SourceLocation(), SourceLocation()), - OMPClauseWithPreInit(this) {} - - /// Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - - /// Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } + OMPFinalClause() : OMPOneStmtClause(), OMPClauseWithPreInit(this) {} /// Returns condition. - Expr *getCondition() const { return cast_or_null<Expr>(Condition); } - - child_range children() { return child_range(&Condition, &Condition + 1); } - - const_child_range children() const { - return const_child_range(&Condition, &Condition + 1); - } + Expr *getCondition() const { return getStmtAs<Expr>(); } child_range used_children(); const_child_range used_children() const { auto Children = const_cast<OMPFinalClause *>(this)->used_children(); return const_child_range(Children.begin(), Children.end()); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_final; - } }; - /// This represents 'num_threads' clause in the '#pragma omp ...' /// directive. /// @@ -596,17 +671,13 @@ public: /// \endcode /// In this example directive '#pragma omp parallel' has simple 'num_threads' /// clause with number of threads '6'. -class OMPNumThreadsClause : public OMPClause, public OMPClauseWithPreInit { +class OMPNumThreadsClause final + : public OMPOneStmtClause<llvm::omp::OMPC_num_threads, OMPClause>, + public OMPClauseWithPreInit { friend class OMPClauseReader; - /// Location of '('. - SourceLocation LParenLoc; - - /// Condition of the 'num_threads' clause. - Stmt *NumThreads = nullptr; - /// Set condition. - void setNumThreads(Expr *NThreads) { NumThreads = NThreads; } + void setNumThreads(Expr *NThreads) { setStmt(NThreads); } public: /// Build 'num_threads' clause with condition \a NumThreads. @@ -622,43 +693,16 @@ public: OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(llvm::omp::OMPC_num_threads, StartLoc, EndLoc), - OMPClauseWithPreInit(this), LParenLoc(LParenLoc), - NumThreads(NumThreads) { + : OMPOneStmtClause(NumThreads, StartLoc, LParenLoc, EndLoc), + OMPClauseWithPreInit(this) { setPreInitStmt(HelperNumThreads, CaptureRegion); } /// Build an empty clause. - OMPNumThreadsClause() - : OMPClause(llvm::omp::OMPC_num_threads, SourceLocation(), - SourceLocation()), - OMPClauseWithPreInit(this) {} - - /// Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - - /// Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } + OMPNumThreadsClause() : OMPOneStmtClause(), OMPClauseWithPreInit(this) {} /// Returns number of threads. - Expr *getNumThreads() const { return cast_or_null<Expr>(NumThreads); } - - child_range children() { return child_range(&NumThreads, &NumThreads + 1); } - - const_child_range children() const { - return const_child_range(&NumThreads, &NumThreads + 1); - } - - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_num_threads; - } + Expr *getNumThreads() const { return getStmtAs<Expr>(); } }; /// This represents 'safelen' clause in the '#pragma omp ...' @@ -673,17 +717,12 @@ public: /// concurrently with SIMD instructions can have a greater distance /// in the logical iteration space than its value. The parameter of /// the safelen clause must be a constant positive integer expression. -class OMPSafelenClause : public OMPClause { +class OMPSafelenClause final + : public OMPOneStmtClause<llvm::omp::OMPC_safelen, OMPClause> { friend class OMPClauseReader; - /// Location of '('. - SourceLocation LParenLoc; - - /// Safe iteration space distance. - Stmt *Safelen = nullptr; - /// Set safelen. - void setSafelen(Expr *Len) { Safelen = Len; } + void setSafelen(Expr *Len) { setStmt(Len); } public: /// Build 'safelen' clause. @@ -693,39 +732,13 @@ public: /// \param EndLoc Ending location of the clause. OMPSafelenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(llvm::omp::OMPC_safelen, StartLoc, EndLoc), - LParenLoc(LParenLoc), Safelen(Len) {} + : OMPOneStmtClause(Len, StartLoc, LParenLoc, EndLoc) {} /// Build an empty clause. - explicit OMPSafelenClause() - : OMPClause(llvm::omp::OMPC_safelen, SourceLocation(), SourceLocation()) { - } - - /// Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - - /// Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } + explicit OMPSafelenClause() : OMPOneStmtClause() {} /// Return safe iteration space distance. - Expr *getSafelen() const { return cast_or_null<Expr>(Safelen); } - - child_range children() { return child_range(&Safelen, &Safelen + 1); } - - const_child_range children() const { - return const_child_range(&Safelen, &Safelen + 1); - } - - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_safelen; - } + Expr *getSafelen() const { return getStmtAs<Expr>(); } }; /// This represents 'simdlen' clause in the '#pragma omp ...' @@ -739,17 +752,12 @@ public: /// If the 'simdlen' clause is used then it specifies the preferred number of /// iterations to be executed concurrently. The parameter of the 'simdlen' /// clause must be a constant positive integer expression. -class OMPSimdlenClause : public OMPClause { +class OMPSimdlenClause final + : public OMPOneStmtClause<llvm::omp::OMPC_simdlen, OMPClause> { friend class OMPClauseReader; - /// Location of '('. - SourceLocation LParenLoc; - - /// Safe iteration space distance. - Stmt *Simdlen = nullptr; - /// Set simdlen. - void setSimdlen(Expr *Len) { Simdlen = Len; } + void setSimdlen(Expr *Len) { setStmt(Len); } public: /// Build 'simdlen' clause. @@ -759,39 +767,13 @@ public: /// \param EndLoc Ending location of the clause. OMPSimdlenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(llvm::omp::OMPC_simdlen, StartLoc, EndLoc), - LParenLoc(LParenLoc), Simdlen(Len) {} + : OMPOneStmtClause(Len, StartLoc, LParenLoc, EndLoc) {} /// Build an empty clause. - explicit OMPSimdlenClause() - : OMPClause(llvm::omp::OMPC_simdlen, SourceLocation(), SourceLocation()) { - } - - /// Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - - /// Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } + explicit OMPSimdlenClause() : OMPOneStmtClause() {} /// Return safe iteration space distance. - Expr *getSimdlen() const { return cast_or_null<Expr>(Simdlen); } - - child_range children() { return child_range(&Simdlen, &Simdlen + 1); } - - const_child_range children() const { - return const_child_range(&Simdlen, &Simdlen + 1); - } - - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_simdlen; - } + Expr *getSimdlen() const { return getStmtAs<Expr>(); } }; /// This represents the 'sizes' clause in the '#pragma omp tile' directive. @@ -894,11 +876,11 @@ public: /// #pragma omp unroll full /// for (int i = 0; i < 64; ++i) /// \endcode -class OMPFullClause final : public OMPClause { +class OMPFullClause final : public OMPNoChildClause<llvm::omp::OMPC_full> { friend class OMPClauseReader; /// Build an empty clause. - explicit OMPFullClause() : OMPClause(llvm::omp::OMPC_full, {}, {}) {} + explicit OMPFullClause() : OMPNoChildClause() {} public: /// Build an AST node for a 'full' clause. @@ -913,22 +895,6 @@ public: /// /// \param C Context of the AST. static OMPFullClause *CreateEmpty(const ASTContext &C); - - child_range children() { return {child_iterator(), child_iterator()}; } - const_child_range children() const { - return {const_child_iterator(), const_child_iterator()}; - } - - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_full; - } }; /// Representation of the 'partial' clause of the '#pragma omp unroll' @@ -1007,17 +973,12 @@ public: /// The parameter must be a constant positive integer expression, it specifies /// the number of nested loops that should be collapsed into a single iteration /// space. -class OMPCollapseClause : public OMPClause { +class OMPCollapseClause final + : public OMPOneStmtClause<llvm::omp::OMPC_collapse, OMPClause> { friend class OMPClauseReader; - /// Location of '('. - SourceLocation LParenLoc; - - /// Number of for-loops. - Stmt *NumForLoops = nullptr; - /// Set the number of associated for-loops. - void setNumForLoops(Expr *Num) { NumForLoops = Num; } + void setNumForLoops(Expr *Num) { setStmt(Num); } public: /// Build 'collapse' clause. @@ -1028,39 +989,13 @@ public: /// \param EndLoc Ending location of the clause. OMPCollapseClause(Expr *Num, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(llvm::omp::OMPC_collapse, StartLoc, EndLoc), - LParenLoc(LParenLoc), NumForLoops(Num) {} + : OMPOneStmtClause(Num, StartLoc, LParenLoc, EndLoc) {} /// Build an empty clause. - explicit OMPCollapseClause() - : OMPClause(llvm::omp::OMPC_collapse, SourceLocation(), - SourceLocation()) {} - - /// Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - - /// Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } + explicit OMPCollapseClause() : OMPOneStmtClause() {} /// Return the number of associated for-loops. - Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); } - - child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); } - - const_child_range children() const { - return const_child_range(&NumForLoops, &NumForLoops + 1); - } - - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_collapse; - } + Expr *getNumForLoops() const { return getStmtAs<Expr>(); } }; /// This represents 'default' clause in the '#pragma omp ...' directive. @@ -1233,7 +1168,8 @@ public: /// \endcode /// In this example directive '#pragma omp requires' has 'unified_address' /// clause. -class OMPUnifiedAddressClause final : public OMPClause { +class OMPUnifiedAddressClause final + : public OMPNoChildClause<llvm::omp::OMPC_unified_address> { public: friend class OMPClauseReader; /// Build 'unified_address' clause. @@ -1241,31 +1177,10 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(llvm::omp::OMPC_unified_address, StartLoc, EndLoc) {} + : OMPNoChildClause(StartLoc, EndLoc) {} /// Build an empty clause. - OMPUnifiedAddressClause() - : OMPClause(llvm::omp::OMPC_unified_address, SourceLocation(), - SourceLocation()) {} - - 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()); - } - - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_unified_address; - } + OMPUnifiedAddressClause() : OMPNoChildClause() {} }; /// This represents 'unified_shared_memory' clause in the '#pragma omp requires' @@ -1487,6 +1402,231 @@ public: } }; +/// This represents 'at' clause in the '#pragma omp error' directive +/// +/// \code +/// #pragma omp error at(compilation) +/// \endcode +/// In this example directive '#pragma omp error' has simple +/// 'at' clause with kind 'complilation'. +class OMPAtClause final : public OMPClause { + friend class OMPClauseReader; + + /// Location of '(' + SourceLocation LParenLoc; + + /// A kind of the 'at' clause. + OpenMPAtClauseKind Kind = OMPC_AT_unknown; + + /// Start location of the kind in source code. + SourceLocation KindKwLoc; + + /// Set kind of the clause. + /// + /// \param K Kind of clause. + void setAtKind(OpenMPAtClauseKind K) { Kind = K; } + + /// Set clause kind location. + /// + /// \param KLoc Kind location. + void setAtKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + +public: + /// Build 'at' clause with argument \a A ('compilation' or 'execution'). + /// + /// \param A Argument of the clause ('compilation' or 'execution'). + /// \param ALoc Starting location of the argument. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + OMPAtClause(OpenMPAtClauseKind A, SourceLocation ALoc, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_at, StartLoc, EndLoc), LParenLoc(LParenLoc), + Kind(A), KindKwLoc(ALoc) {} + + /// Build an empty clause. + OMPAtClause() + : OMPClause(llvm::omp::OMPC_at, SourceLocation(), SourceLocation()) {} + + /// Returns the locaiton of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// Returns kind of the clause. + OpenMPAtClauseKind getAtKind() const { return Kind; } + + /// Returns location of clause kind. + SourceLocation getAtKindKwLoc() const { return KindKwLoc; } + + 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()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_at; + } +}; + +/// This represents 'severity' clause in the '#pragma omp error' directive +/// +/// \code +/// #pragma omp error severity(fatal) +/// \endcode +/// In this example directive '#pragma omp error' has simple +/// 'severity' clause with kind 'fatal'. +class OMPSeverityClause final : public OMPClause { + friend class OMPClauseReader; + + /// Location of '(' + SourceLocation LParenLoc; + + /// A kind of the 'severity' clause. + OpenMPSeverityClauseKind Kind = OMPC_SEVERITY_unknown; + + /// Start location of the kind in source code. + SourceLocation KindKwLoc; + + /// Set kind of the clause. + /// + /// \param K Kind of clause. + void setSeverityKind(OpenMPSeverityClauseKind K) { Kind = K; } + + /// Set clause kind location. + /// + /// \param KLoc Kind location. + void setSeverityKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + +public: + /// Build 'severity' clause with argument \a A ('fatal' or 'warning'). + /// + /// \param A Argument of the clause ('fatal' or 'warning'). + /// \param ALoc Starting location of the argument. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + OMPSeverityClause(OpenMPSeverityClauseKind A, SourceLocation ALoc, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_severity, StartLoc, EndLoc), + LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc) {} + + /// Build an empty clause. + OMPSeverityClause() + : OMPClause(llvm::omp::OMPC_severity, SourceLocation(), + SourceLocation()) {} + + /// Returns the locaiton of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// Returns kind of the clause. + OpenMPSeverityClauseKind getSeverityKind() const { return Kind; } + + /// Returns location of clause kind. + SourceLocation getSeverityKindKwLoc() const { return KindKwLoc; } + + 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()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_severity; + } +}; + +/// This represents 'message' clause in the '#pragma omp error' directive +/// +/// \code +/// #pragma omp error message("GNU compiler required.") +/// \endcode +/// In this example directive '#pragma omp error' has simple +/// 'message' clause with user error message of "GNU compiler required.". +class OMPMessageClause final : public OMPClause { + friend class OMPClauseReader; + + /// Location of '(' + SourceLocation LParenLoc; + + // Expression of the 'message' clause. + Stmt *MessageString = nullptr; + + /// Set message string of the clause. + void setMessageString(Expr *MS) { MessageString = MS; } + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + +public: + /// Build 'message' clause with message string argument + /// + /// \param MS Argument of the clause (message string). + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + OMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_message, StartLoc, EndLoc), + LParenLoc(LParenLoc), MessageString(MS) {} + + /// Build an empty clause. + OMPMessageClause() + : OMPClause(llvm::omp::OMPC_message, SourceLocation(), SourceLocation()) { + } + + /// Returns the locaiton of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// Returns message string of the clause. + Expr *getMessageString() const { return cast_or_null<Expr>(MessageString); } + + child_range children() { + return child_range(&MessageString, &MessageString + 1); + } + + const_child_range children() const { + return const_child_range(&MessageString, &MessageString + 1); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_message; + } +}; + /// This represents 'schedule' clause in the '#pragma omp ...' directive. /// /// \code @@ -1782,37 +1922,15 @@ public: /// #pragma omp for nowait /// \endcode /// In this example directive '#pragma omp for' has 'nowait' clause. -class OMPNowaitClause : public OMPClause { +class OMPNowaitClause final : public OMPNoChildClause<llvm::omp::OMPC_nowait> { public: /// Build 'nowait' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - OMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(llvm::omp::OMPC_nowait, StartLoc, EndLoc) {} - - /// Build an empty clause. - OMPNowaitClause() - : OMPClause(llvm::omp::OMPC_nowait, SourceLocation(), SourceLocation()) {} - - 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()); - } - - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_nowait; - } + OMPNowaitClause(SourceLocation StartLoc = SourceLocation(), + SourceLocation EndLoc = SourceLocation()) + : OMPNoChildClause(StartLoc, EndLoc) {} }; /// This represents 'untied' clause in the '#pragma omp ...' directive. @@ -2005,13 +2123,13 @@ class OMPUpdateClause final return IsExtended ? 2 : 0; } - /// Sets the the location of '(' in clause for 'depobj' directive. + /// Sets the location of '(' in clause for 'depobj' directive. void setLParenLoc(SourceLocation Loc) { assert(IsExtended && "Expected extended clause."); *getTrailingObjects<SourceLocation>() = Loc; } - /// Sets the the location of '(' in clause for 'depobj' directive. + /// Sets the location of '(' in clause for 'depobj' directive. void setArgumentLoc(SourceLocation Loc) { assert(IsExtended && "Expected extended clause."); *std::next(getTrailingObjects<SourceLocation>(), 1) = Loc; @@ -2085,13 +2203,13 @@ public: return const_child_range(const_child_iterator(), const_child_iterator()); } - /// Gets the the location of '(' in clause for 'depobj' directive. + /// Gets the location of '(' in clause for 'depobj' directive. SourceLocation getLParenLoc() const { assert(IsExtended && "Expected extended clause."); return *getTrailingObjects<SourceLocation>(); } - /// Gets the the location of argument in clause for 'depobj' directive. + /// Gets the location of argument in clause for 'depobj' directive. SourceLocation getArgumentLoc() const { assert(IsExtended && "Expected extended clause."); return *std::next(getTrailingObjects<SourceLocation>(), 1); @@ -2149,6 +2267,47 @@ public: } }; +/// This represents 'compare' clause in the '#pragma omp atomic' +/// directive. +/// +/// \code +/// #pragma omp atomic compare +/// \endcode +/// In this example directive '#pragma omp atomic' has 'compare' clause. +class OMPCompareClause final : public OMPClause { +public: + /// Build 'compare' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + OMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_compare, StartLoc, EndLoc) {} + + /// Build an empty clause. + OMPCompareClause() + : OMPClause(llvm::omp::OMPC_compare, SourceLocation(), SourceLocation()) { + } + + 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()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_compare; + } +}; + /// This represents 'seq_cst' clause in the '#pragma omp atomic' /// directive. /// @@ -2354,6 +2513,89 @@ public: } }; +/// This represents 'fail' clause in the '#pragma omp atomic' +/// directive. +/// +/// \code +/// #pragma omp atomic compare fail +/// \endcode +/// In this example directive '#pragma omp atomic compare' has 'fail' clause. +class OMPFailClause final : public OMPClause { + + // FailParameter is a memory-order-clause. Storing the ClauseKind is + // sufficient for our purpose. + OpenMPClauseKind FailParameter = llvm::omp::Clause::OMPC_unknown; + SourceLocation FailParameterLoc; + SourceLocation LParenLoc; + + friend class OMPClauseReader; + + /// Sets the location of '(' in fail clause. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + + /// Sets the location of memoryOrder clause argument in fail clause. + void setFailParameterLoc(SourceLocation Loc) { FailParameterLoc = Loc; } + + /// Sets the mem_order clause for 'atomic compare fail' directive. + void setFailParameter(OpenMPClauseKind FailParameter) { + this->FailParameter = FailParameter; + assert(checkFailClauseParameter(FailParameter) && + "Invalid fail clause parameter"); + } + +public: + /// Build 'fail' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + OMPFailClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_fail, StartLoc, EndLoc) {} + + OMPFailClause(OpenMPClauseKind FailParameter, SourceLocation FailParameterLoc, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_fail, StartLoc, EndLoc), + FailParameterLoc(FailParameterLoc), LParenLoc(LParenLoc) { + + setFailParameter(FailParameter); + } + + /// Build an empty clause. + OMPFailClause() + : OMPClause(llvm::omp::OMPC_fail, SourceLocation(), SourceLocation()) {} + + 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()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_fail; + } + + /// Gets the location of '(' (for the parameter) in fail clause. + SourceLocation getLParenLoc() const { + return LParenLoc; + } + + /// Gets the location of Fail Parameter (type memory-order-clause) in + /// fail clause. + SourceLocation getFailParameterLoc() const { return FailParameterLoc; } + + /// Gets the parameter (type memory-order-clause) in Fail clause. + OpenMPClauseKind getFailParameter() const { return FailParameter; } +}; + /// This represents clause 'private' in the '#pragma omp ...' directives. /// /// \code @@ -2398,7 +2640,7 @@ class OMPPrivateClause final return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } ArrayRef<const Expr *> getPrivateCopies() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); + return llvm::ArrayRef(varlist_end(), varlist_size()); } public: @@ -2507,7 +2749,7 @@ class OMPFirstprivateClause final return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } ArrayRef<const Expr *> getPrivateCopies() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); + return llvm::ArrayRef(varlist_end(), varlist_size()); } /// Sets the list of references to initializer variables for new @@ -2521,7 +2763,7 @@ class OMPFirstprivateClause final return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size()); } ArrayRef<const Expr *> getInits() const { - return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size()); + return llvm::ArrayRef(getPrivateCopies().end(), varlist_size()); } public: @@ -2669,7 +2911,7 @@ class OMPLastprivateClause final return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } ArrayRef<const Expr *> getPrivateCopies() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); + return llvm::ArrayRef(varlist_end(), varlist_size()); } /// Set list of helper expressions, required for proper codegen of the @@ -2683,7 +2925,7 @@ class OMPLastprivateClause final return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size()); } ArrayRef<const Expr *> getSourceExprs() const { - return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size()); + return llvm::ArrayRef(getPrivateCopies().end(), varlist_size()); } /// Set list of helper expressions, required for proper codegen of the @@ -2697,7 +2939,7 @@ class OMPLastprivateClause final return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size()); } ArrayRef<const Expr *> getDestinationExprs() const { - return llvm::makeArrayRef(getSourceExprs().end(), varlist_size()); + return llvm::ArrayRef(getSourceExprs().end(), varlist_size()); } /// Set list of helper assignment expressions, required for proper @@ -2710,7 +2952,7 @@ class OMPLastprivateClause final return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size()); } ArrayRef<const Expr *> getAssignmentOps() const { - return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size()); + return llvm::ArrayRef(getDestinationExprs().end(), varlist_size()); } /// Sets lastprivate kind. @@ -2998,7 +3240,7 @@ class OMPReductionClause final return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } ArrayRef<const Expr *> getPrivates() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); + return llvm::ArrayRef(varlist_end(), varlist_size()); } /// Set list of helper expressions, required for proper codegen of the @@ -3011,7 +3253,7 @@ class OMPReductionClause final return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size()); } ArrayRef<const Expr *> getLHSExprs() const { - return llvm::makeArrayRef(getPrivates().end(), varlist_size()); + return llvm::ArrayRef(getPrivates().end(), varlist_size()); } /// Set list of helper expressions, required for proper codegen of the @@ -3026,7 +3268,7 @@ class OMPReductionClause final return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size()); } ArrayRef<const Expr *> getRHSExprs() const { - return llvm::makeArrayRef(getLHSExprs().end(), varlist_size()); + return llvm::ArrayRef(getLHSExprs().end(), varlist_size()); } /// Set list of helper reduction expressions, required for proper @@ -3040,7 +3282,7 @@ class OMPReductionClause final return MutableArrayRef<Expr *>(getRHSExprs().end(), varlist_size()); } ArrayRef<const Expr *> getReductionOps() const { - return llvm::makeArrayRef(getRHSExprs().end(), varlist_size()); + return llvm::ArrayRef(getRHSExprs().end(), varlist_size()); } /// Set list of helper copy operations for inscan reductions. @@ -3052,7 +3294,7 @@ class OMPReductionClause final return MutableArrayRef<Expr *>(getReductionOps().end(), varlist_size()); } ArrayRef<const Expr *> getInscanCopyOps() const { - return llvm::makeArrayRef(getReductionOps().end(), varlist_size()); + return llvm::ArrayRef(getReductionOps().end(), varlist_size()); } /// Set list of helper temp vars for inscan copy array operations. @@ -3063,7 +3305,7 @@ class OMPReductionClause final return MutableArrayRef<Expr *>(getInscanCopyOps().end(), varlist_size()); } ArrayRef<const Expr *> getInscanCopyArrayTemps() const { - return llvm::makeArrayRef(getInscanCopyOps().end(), varlist_size()); + return llvm::ArrayRef(getInscanCopyOps().end(), varlist_size()); } /// Set list of helper temp elements vars for inscan copy array operations. @@ -3075,7 +3317,7 @@ class OMPReductionClause final varlist_size()); } ArrayRef<const Expr *> getInscanCopyArrayElems() const { - return llvm::makeArrayRef(getInscanCopyArrayTemps().end(), varlist_size()); + return llvm::ArrayRef(getInscanCopyArrayTemps().end(), varlist_size()); } public: @@ -3317,7 +3559,7 @@ class OMPTaskReductionClause final return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } ArrayRef<const Expr *> getPrivates() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); + return llvm::ArrayRef(varlist_end(), varlist_size()); } /// Set list of helper expressions, required for proper codegen of the clause. @@ -3330,7 +3572,7 @@ class OMPTaskReductionClause final return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size()); } ArrayRef<const Expr *> getLHSExprs() const { - return llvm::makeArrayRef(getPrivates().end(), varlist_size()); + return llvm::ArrayRef(getPrivates().end(), varlist_size()); } /// Set list of helper expressions, required for proper codegen of the clause. @@ -3344,7 +3586,7 @@ class OMPTaskReductionClause final return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size()); } ArrayRef<const Expr *> getRHSExprs() const { - return llvm::makeArrayRef(getLHSExprs().end(), varlist_size()); + return llvm::ArrayRef(getLHSExprs().end(), varlist_size()); } /// Set list of helper reduction expressions, required for proper @@ -3358,7 +3600,7 @@ class OMPTaskReductionClause final return MutableArrayRef<Expr *>(getRHSExprs().end(), varlist_size()); } ArrayRef<const Expr *> getReductionOps() const { - return llvm::makeArrayRef(getRHSExprs().end(), varlist_size()); + return llvm::ArrayRef(getRHSExprs().end(), varlist_size()); } public: @@ -3548,7 +3790,7 @@ class OMPInReductionClause final return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } ArrayRef<const Expr *> getPrivates() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); + return llvm::ArrayRef(varlist_end(), varlist_size()); } /// Set list of helper expressions, required for proper codegen of the clause. @@ -3561,7 +3803,7 @@ class OMPInReductionClause final return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size()); } ArrayRef<const Expr *> getLHSExprs() const { - return llvm::makeArrayRef(getPrivates().end(), varlist_size()); + return llvm::ArrayRef(getPrivates().end(), varlist_size()); } /// Set list of helper expressions, required for proper codegen of the clause. @@ -3575,7 +3817,7 @@ class OMPInReductionClause final return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size()); } ArrayRef<const Expr *> getRHSExprs() const { - return llvm::makeArrayRef(getLHSExprs().end(), varlist_size()); + return llvm::ArrayRef(getLHSExprs().end(), varlist_size()); } /// Set list of helper reduction expressions, required for proper @@ -3589,7 +3831,7 @@ class OMPInReductionClause final return MutableArrayRef<Expr *>(getRHSExprs().end(), varlist_size()); } ArrayRef<const Expr *> getReductionOps() const { - return llvm::makeArrayRef(getRHSExprs().end(), varlist_size()); + return llvm::ArrayRef(getRHSExprs().end(), varlist_size()); } /// Set list of helper reduction taskgroup descriptors. @@ -3600,7 +3842,7 @@ class OMPInReductionClause final return MutableArrayRef<Expr *>(getReductionOps().end(), varlist_size()); } ArrayRef<const Expr *> getTaskgroupDescriptors() const { - return llvm::makeArrayRef(getReductionOps().end(), varlist_size()); + return llvm::ArrayRef(getReductionOps().end(), varlist_size()); } public: @@ -3759,6 +4001,9 @@ class OMPLinearClause final /// Location of ':'. SourceLocation ColonLoc; + /// Location of 'step' modifier. + SourceLocation StepModifierLoc; + /// Sets the linear step for clause. void setStep(Expr *Step) { *(getFinals().end()) = Step; } @@ -3770,16 +4015,18 @@ class OMPLinearClause final /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param ColonLoc Location of ':'. + /// \param StepModifierLoc Location of 'step' modifier. /// \param EndLoc Ending location of the clause. /// \param NumVars Number of variables. OMPLinearClause(SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, - SourceLocation ColonLoc, SourceLocation EndLoc, - unsigned NumVars) + SourceLocation ColonLoc, SourceLocation StepModifierLoc, + SourceLocation EndLoc, unsigned NumVars) : OMPVarListClause<OMPLinearClause>(llvm::omp::OMPC_linear, StartLoc, LParenLoc, EndLoc, NumVars), OMPClauseWithPostUpdate(this), Modifier(Modifier), - ModifierLoc(ModifierLoc), ColonLoc(ColonLoc) {} + ModifierLoc(ModifierLoc), ColonLoc(ColonLoc), + StepModifierLoc(StepModifierLoc) {} /// Build an empty clause. /// @@ -3806,14 +4053,14 @@ class OMPLinearClause final return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } ArrayRef<const Expr *> getPrivates() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); + return llvm::ArrayRef(varlist_end(), varlist_size()); } MutableArrayRef<Expr *> getInits() { return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size()); } ArrayRef<const Expr *> getInits() const { - return llvm::makeArrayRef(getPrivates().end(), varlist_size()); + return llvm::ArrayRef(getPrivates().end(), varlist_size()); } /// Sets the list of update expressions for linear variables. @@ -3821,7 +4068,7 @@ class OMPLinearClause final return MutableArrayRef<Expr *>(getInits().end(), varlist_size()); } ArrayRef<const Expr *> getUpdates() const { - return llvm::makeArrayRef(getInits().end(), varlist_size()); + return llvm::ArrayRef(getInits().end(), varlist_size()); } /// Sets the list of final update expressions for linear variables. @@ -3829,7 +4076,7 @@ class OMPLinearClause final return MutableArrayRef<Expr *>(getUpdates().end(), varlist_size()); } ArrayRef<const Expr *> getFinals() const { - return llvm::makeArrayRef(getUpdates().end(), varlist_size()); + return llvm::ArrayRef(getUpdates().end(), varlist_size()); } /// Gets the list of used expressions for linear variables. @@ -3837,7 +4084,7 @@ class OMPLinearClause final return MutableArrayRef<Expr *>(getFinals().end() + 2, varlist_size() + 1); } ArrayRef<const Expr *> getUsedExprs() const { - return llvm::makeArrayRef(getFinals().end() + 2, varlist_size() + 1); + return llvm::ArrayRef(getFinals().end() + 2, varlist_size() + 1); } /// Sets the list of the copies of original linear variables. @@ -3858,6 +4105,7 @@ public: /// \param Modifier Modifier of 'linear' clause. /// \param ModifierLoc Modifier location. /// \param ColonLoc Location of ':'. + /// \param StepModifierLoc Location of 'step' modifier. /// \param EndLoc Ending location of the clause. /// \param VL List of references to the variables. /// \param PL List of private copies of original variables. @@ -3871,9 +4119,10 @@ public: static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, - SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, - ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep, - Stmt *PreInit, Expr *PostUpdate); + SourceLocation ColonLoc, SourceLocation StepModifierLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> PL, + ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, + Expr *PostUpdate); /// Creates an empty clause with the place for \a NumVars variables. /// @@ -3896,9 +4145,15 @@ public: /// Sets the location of ':'. void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + /// Sets the location of 'step' modifier. + void setStepModifierLoc(SourceLocation Loc) { StepModifierLoc = Loc; } + /// Returns the location of ':'. SourceLocation getColonLoc() const { return ColonLoc; } + /// Returns the location of 'step' modifier. + SourceLocation getStepModifierLoc() const { return StepModifierLoc; } + /// Returns linear step. Expr *getStep() { return *(getFinals().end()); } @@ -4166,7 +4421,7 @@ class OMPCopyinClause final return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } ArrayRef<const Expr *> getSourceExprs() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); + return llvm::ArrayRef(varlist_end(), varlist_size()); } /// Set list of helper expressions, required for proper codegen of the @@ -4179,7 +4434,7 @@ class OMPCopyinClause final return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size()); } ArrayRef<const Expr *> getDestinationExprs() const { - return llvm::makeArrayRef(getSourceExprs().end(), varlist_size()); + return llvm::ArrayRef(getSourceExprs().end(), varlist_size()); } /// Set list of helper assignment expressions, required for proper @@ -4193,7 +4448,7 @@ class OMPCopyinClause final return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size()); } ArrayRef<const Expr *> getAssignmentOps() const { - return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size()); + return llvm::ArrayRef(getDestinationExprs().end(), varlist_size()); } public: @@ -4331,7 +4586,7 @@ class OMPCopyprivateClause final return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } ArrayRef<const Expr *> getSourceExprs() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); + return llvm::ArrayRef(varlist_end(), varlist_size()); } /// Set list of helper expressions, required for proper codegen of the @@ -4344,7 +4599,7 @@ class OMPCopyprivateClause final return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size()); } ArrayRef<const Expr *> getDestinationExprs() const { - return llvm::makeArrayRef(getSourceExprs().end(), varlist_size()); + return llvm::ArrayRef(getSourceExprs().end(), varlist_size()); } /// Set list of helper assignment expressions, required for proper @@ -4358,7 +4613,7 @@ class OMPCopyprivateClause final return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size()); } ArrayRef<const Expr *> getAssignmentOps() const { - return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size()); + return llvm::ArrayRef(getDestinationExprs().end(), varlist_size()); } public: @@ -4629,14 +4884,24 @@ class OMPDependClause final friend OMPVarListClause; friend TrailingObjects; - /// Dependency type (one of in, out, inout). - OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; +public: + struct DependDataTy final { + /// Dependency type (one of in, out, inout). + OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; - /// Dependency type location. - SourceLocation DepLoc; + /// Dependency type location. + SourceLocation DepLoc; - /// Colon location. - SourceLocation ColonLoc; + /// Colon location. + SourceLocation ColonLoc; + + /// Location of 'omp_all_memory'. + SourceLocation OmpAllMemoryLoc; + }; + +private: + /// Dependency type and source locations. + DependDataTy Data; /// Number of loops, associated with the depend clause. unsigned NumLoops = 0; @@ -4667,13 +4932,16 @@ class OMPDependClause final NumLoops(NumLoops) {} /// Set dependency kind. - void setDependencyKind(OpenMPDependClauseKind K) { DepKind = K; } + void setDependencyKind(OpenMPDependClauseKind K) { Data.DepKind = K; } /// Set dependency kind and its location. - void setDependencyLoc(SourceLocation Loc) { DepLoc = Loc; } + void setDependencyLoc(SourceLocation Loc) { Data.DepLoc = Loc; } /// Set colon location. - void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + void setColonLoc(SourceLocation Loc) { Data.ColonLoc = Loc; } + + /// Set the 'omp_all_memory' location. + void setOmpAllMemoryLoc(SourceLocation Loc) { Data.OmpAllMemoryLoc = Loc; } /// Sets optional dependency modifier. void setModifier(Expr *DepModifier); @@ -4685,18 +4953,15 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - /// \param DepKind Dependency type. - /// \param DepLoc Location of the dependency type. - /// \param ColonLoc Colon location. + /// \param Data Dependency type and source locations. /// \param VL List of references to the variables. /// \param NumLoops Number of loops that is associated with this depend /// clause. static OMPDependClause *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, Expr *DepModifier, - OpenMPDependClauseKind DepKind, - SourceLocation DepLoc, SourceLocation ColonLoc, - ArrayRef<Expr *> VL, unsigned NumLoops); + SourceLocation EndLoc, DependDataTy Data, + Expr *DepModifier, ArrayRef<Expr *> VL, + unsigned NumLoops); /// Creates an empty clause with \a N variables. /// @@ -4708,7 +4973,16 @@ public: unsigned NumLoops); /// Get dependency type. - OpenMPDependClauseKind getDependencyKind() const { return DepKind; } + OpenMPDependClauseKind getDependencyKind() const { return Data.DepKind; } + + /// Get dependency type location. + SourceLocation getDependencyLoc() const { return Data.DepLoc; } + + /// Get colon location. + SourceLocation getColonLoc() const { return Data.ColonLoc; } + + /// Get 'omp_all_memory' location. + SourceLocation getOmpAllMemoryLoc() const { return Data.OmpAllMemoryLoc; } /// Return optional depend modifier. Expr *getModifier(); @@ -4716,12 +4990,6 @@ public: return const_cast<OMPDependClause *>(this)->getModifier(); } - /// Get dependency type location. - SourceLocation getDependencyLoc() const { return DepLoc; } - - /// Get colon location. - SourceLocation getColonLoc() const { return ColonLoc; } - /// Get number of loops associated with the clause. unsigned getNumLoops() const { return NumLoops; } @@ -4857,38 +5125,18 @@ public: /// #pragma omp ordered threads /// \endcode /// In this example directive '#pragma omp ordered' has simple 'threads' clause. -class OMPThreadsClause : public OMPClause { +class OMPThreadsClause final + : public OMPNoChildClause<llvm::omp::OMPC_threads> { public: /// Build 'threads' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(llvm::omp::OMPC_threads, StartLoc, EndLoc) {} + : OMPNoChildClause(StartLoc, EndLoc) {} /// Build an empty clause. - OMPThreadsClause() - : OMPClause(llvm::omp::OMPC_threads, SourceLocation(), SourceLocation()) { - } - - 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()); - } - - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_threads; - } + OMPThreadsClause() : OMPNoChildClause() {} }; /// This represents 'simd' clause in the '#pragma omp ...' directive. @@ -5273,7 +5521,7 @@ protected: MutableArrayRef<Expr *> getUDMapperRefs() { assert(SupportsMapper && "Must be a clause that is possible to have user-defined mappers"); - return llvm::makeMutableArrayRef<Expr *>( + return llvm::MutableArrayRef<Expr *>( static_cast<T *>(this)->template getTrailingObjects<Expr *>() + OMPVarListClause<T>::varlist_size(), OMPVarListClause<T>::varlist_size()); @@ -5284,7 +5532,7 @@ protected: ArrayRef<Expr *> getUDMapperRefs() const { assert(SupportsMapper && "Must be a clause that is possible to have user-defined mappers"); - return llvm::makeArrayRef<Expr *>( + return llvm::ArrayRef<Expr *>( static_cast<const T *>(this)->template getTrailingObjects<Expr *>() + OMPVarListClause<T>::varlist_size(), OMPVarListClause<T>::varlist_size()); @@ -5483,14 +5731,14 @@ public: return const_component_lists_iterator( getUniqueDeclsRef(), getDeclNumListsRef(), getComponentListSizesRef(), getComponentsRef(), SupportsMapper, - SupportsMapper ? getUDMapperRefs() : llvm::None); + SupportsMapper ? getUDMapperRefs() : std::nullopt); } const_component_lists_iterator component_lists_end() const { return const_component_lists_iterator( ArrayRef<ValueDecl *>(), ArrayRef<unsigned>(), ArrayRef<unsigned>(), MappableExprComponentListRef(getComponentsRef().end(), getComponentsRef().end()), - SupportsMapper, llvm::None); + SupportsMapper, std::nullopt); } const_component_lists_range component_lists() const { return {component_lists_begin(), component_lists_end()}; @@ -5503,7 +5751,7 @@ public: return const_component_lists_iterator( VD, getUniqueDeclsRef(), getDeclNumListsRef(), getComponentListSizesRef(), getComponentsRef(), SupportsMapper, - SupportsMapper ? getUDMapperRefs() : llvm::None); + SupportsMapper ? getUDMapperRefs() : std::nullopt); } const_component_lists_iterator decl_component_lists_end() const { return component_lists_end(); @@ -5593,7 +5841,7 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, size_t numTrailingObjects(OverloadToken<Expr *>) const { // There are varlist_size() of expressions, and varlist_size() of // user-defined mappers. - return 2 * varlist_size(); + return 2 * varlist_size() + 1; } size_t numTrailingObjects(OverloadToken<ValueDecl *>) const { return getUniqueDeclarationsNum(); @@ -5606,6 +5854,7 @@ private: /// Map-type-modifiers for the 'map' clause. OpenMPMapModifierKind MapTypeModifiers[NumberOfOMPMapClauseModifiers] = { OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, + OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown}; /// Location of map-type-modifiers for the 'map' clause. @@ -5654,12 +5903,11 @@ private: /*SupportsMapper=*/true, &MapperQualifierLoc, &MapperIdInfo), MapType(MapType), MapTypeIsImplicit(MapTypeIsImplicit), MapLoc(MapLoc) { - assert(llvm::array_lengthof(MapTypeModifiers) == MapModifiers.size() && + assert(std::size(MapTypeModifiers) == MapModifiers.size() && "Unexpected number of map type modifiers."); llvm::copy(MapModifiers, std::begin(MapTypeModifiers)); - assert(llvm::array_lengthof(MapTypeModifiersLoc) == - MapModifiersLoc.size() && + assert(std::size(MapTypeModifiersLoc) == MapModifiersLoc.size() && "Unexpected number of map type modifier locations."); llvm::copy(MapModifiersLoc, std::begin(MapTypeModifiersLoc)); } @@ -5708,6 +5956,11 @@ private: /// Set colon location. void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + /// Set iterator modifier. + void setIteratorModifier(Expr *IteratorModifier) { + getTrailingObjects<Expr *>()[2 * varlist_size()] = IteratorModifier; + } + public: /// Creates clause with a list of variables \a VL. /// @@ -5720,6 +5973,7 @@ public: /// \param ComponentLists Component lists used in the clause. /// \param UDMapperRefs References to user-defined mappers associated with /// expressions used in the clause. + /// \param IteratorModifier Iterator modifier. /// \param MapModifiers Map-type-modifiers. /// \param MapModifiersLoc Location of map-type-modifiers. /// \param UDMQualifierLoc C++ nested name specifier for the associated @@ -5732,7 +5986,7 @@ public: Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations, MappableExprComponentListsRef ComponentLists, - ArrayRef<Expr *> UDMapperRefs, + ArrayRef<Expr *> UDMapperRefs, Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapModifiers, ArrayRef<SourceLocation> MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, @@ -5751,6 +6005,11 @@ public: static OMPMapClause *CreateEmpty(const ASTContext &C, const OMPMappableExprListSizeTy &Sizes); + /// Fetches Expr * of iterator modifier. + Expr *getIteratorModifier() { + return getTrailingObjects<Expr *>()[2 * varlist_size()]; + } + /// Fetches mapping kind for the clause. OpenMPMapClauseKind getMapType() const LLVM_READONLY { return MapType; } @@ -5782,12 +6041,12 @@ public: /// Fetches ArrayRef of map-type-modifiers. ArrayRef<OpenMPMapModifierKind> getMapTypeModifiers() const LLVM_READONLY { - return llvm::makeArrayRef(MapTypeModifiers); + return llvm::ArrayRef(MapTypeModifiers); } /// Fetches ArrayRef of location of map-type-modifiers. ArrayRef<SourceLocation> getMapTypeModifiersLoc() const LLVM_READONLY { - return llvm::makeArrayRef(MapTypeModifiersLoc); + return llvm::ArrayRef(MapTypeModifiersLoc); } /// Fetches location of clause mapping kind. @@ -6065,26 +6324,43 @@ class OMPGrainsizeClause : public OMPClause, public OMPClauseWithPreInit { /// Location of '('. SourceLocation LParenLoc; + /// Modifiers for 'grainsize' clause. + OpenMPGrainsizeClauseModifier Modifier = OMPC_GRAINSIZE_unknown; + + /// Location of the modifier. + SourceLocation ModifierLoc; + /// Safe iteration space distance. Stmt *Grainsize = nullptr; /// Set safelen. void setGrainsize(Expr *Size) { Grainsize = Size; } + /// Sets modifier. + void setModifier(OpenMPGrainsizeClauseModifier M) { Modifier = M; } + + /// Sets modifier location. + void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; } + public: /// Build 'grainsize' clause. /// + /// \param Modifier Clause modifier. /// \param Size Expression associated with this clause. /// \param HelperSize Helper grainsize for the construct. /// \param CaptureRegion Innermost OpenMP region where expressions in this /// clause must be captured. /// \param StartLoc Starting location of the clause. + /// \param ModifierLoc Modifier location. + /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - OMPGrainsizeClause(Expr *Size, Stmt *HelperSize, - OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) + OMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, + Stmt *HelperSize, OpenMPDirectiveKind CaptureRegion, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ModifierLoc, SourceLocation EndLoc) : OMPClause(llvm::omp::OMPC_grainsize, StartLoc, EndLoc), - OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Grainsize(Size) { + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Modifier(Modifier), + ModifierLoc(ModifierLoc), Grainsize(Size) { setPreInitStmt(HelperSize, CaptureRegion); } @@ -6103,6 +6379,12 @@ public: /// Return safe iteration space distance. Expr *getGrainsize() const { return cast_or_null<Expr>(Grainsize); } + /// Gets modifier. + OpenMPGrainsizeClauseModifier getModifier() const { return Modifier; } + + /// Gets modifier location. + SourceLocation getModifierLoc() const { return ModifierLoc; } + child_range children() { return child_range(&Grainsize, &Grainsize + 1); } const_child_range children() const { @@ -6174,26 +6456,43 @@ class OMPNumTasksClause : public OMPClause, public OMPClauseWithPreInit { /// Location of '('. SourceLocation LParenLoc; + /// Modifiers for 'num_tasks' clause. + OpenMPNumTasksClauseModifier Modifier = OMPC_NUMTASKS_unknown; + + /// Location of the modifier. + SourceLocation ModifierLoc; + /// Safe iteration space distance. Stmt *NumTasks = nullptr; /// Set safelen. void setNumTasks(Expr *Size) { NumTasks = Size; } + /// Sets modifier. + void setModifier(OpenMPNumTasksClauseModifier M) { Modifier = M; } + + /// Sets modifier location. + void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; } + public: /// Build 'num_tasks' clause. /// + /// \param Modifier Clause modifier. /// \param Size Expression associated with this clause. /// \param HelperSize Helper grainsize for the construct. /// \param CaptureRegion Innermost OpenMP region where expressions in this /// clause must be captured. /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - OMPNumTasksClause(Expr *Size, Stmt *HelperSize, - OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) + /// \param ModifierLoc Modifier location. + /// \param LParenLoc Location of '('. + OMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *Size, + Stmt *HelperSize, OpenMPDirectiveKind CaptureRegion, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ModifierLoc, SourceLocation EndLoc) : OMPClause(llvm::omp::OMPC_num_tasks, StartLoc, EndLoc), - OMPClauseWithPreInit(this), LParenLoc(LParenLoc), NumTasks(Size) { + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Modifier(Modifier), + ModifierLoc(ModifierLoc), NumTasks(Size) { setPreInitStmt(HelperSize, CaptureRegion); } @@ -6212,6 +6511,12 @@ public: /// Return safe iteration space distance. Expr *getNumTasks() const { return cast_or_null<Expr>(NumTasks); } + /// Gets modifier. + OpenMPNumTasksClauseModifier getModifier() const { return Modifier; } + + /// Gets modifier location. + SourceLocation getModifierLoc() const { return ModifierLoc; } + child_range children() { return child_range(&NumTasks, &NumTasks + 1); } const_child_range children() const { @@ -6576,12 +6881,11 @@ class OMPToClause final : public OMPMappableExprListClause<OMPToClause>, : OMPMappableExprListClause(llvm::omp::OMPC_to, Locs, Sizes, /*SupportsMapper=*/true, &MapperQualifierLoc, &MapperIdInfo) { - assert(llvm::array_lengthof(MotionModifiers) == TheMotionModifiers.size() && + assert(std::size(MotionModifiers) == TheMotionModifiers.size() && "Unexpected number of motion modifiers."); llvm::copy(TheMotionModifiers, std::begin(MotionModifiers)); - assert(llvm::array_lengthof(MotionModifiersLoc) == - TheMotionModifiersLoc.size() && + assert(std::size(MotionModifiersLoc) == TheMotionModifiersLoc.size() && "Unexpected number of motion modifier locations."); llvm::copy(TheMotionModifiersLoc, std::begin(MotionModifiersLoc)); } @@ -6693,12 +6997,12 @@ public: /// Fetches ArrayRef of motion-modifiers. ArrayRef<OpenMPMotionModifierKind> getMotionModifiers() const LLVM_READONLY { - return llvm::makeArrayRef(MotionModifiers); + return llvm::ArrayRef(MotionModifiers); } /// Fetches ArrayRef of location of motion-modifiers. ArrayRef<SourceLocation> getMotionModifiersLoc() const LLVM_READONLY { - return llvm::makeArrayRef(MotionModifiersLoc); + return llvm::ArrayRef(MotionModifiersLoc); } /// Get colon location. @@ -6778,12 +7082,11 @@ class OMPFromClause final : OMPMappableExprListClause(llvm::omp::OMPC_from, Locs, Sizes, /*SupportsMapper=*/true, &MapperQualifierLoc, &MapperIdInfo) { - assert(llvm::array_lengthof(MotionModifiers) == TheMotionModifiers.size() && + assert(std::size(MotionModifiers) == TheMotionModifiers.size() && "Unexpected number of motion modifiers."); llvm::copy(TheMotionModifiers, std::begin(MotionModifiers)); - assert(llvm::array_lengthof(MotionModifiersLoc) == - TheMotionModifiersLoc.size() && + assert(std::size(MotionModifiersLoc) == TheMotionModifiersLoc.size() && "Unexpected number of motion modifier locations."); llvm::copy(TheMotionModifiersLoc, std::begin(MotionModifiersLoc)); } @@ -6894,12 +7197,12 @@ public: /// Fetches ArrayRef of motion-modifiers. ArrayRef<OpenMPMotionModifierKind> getMotionModifiers() const LLVM_READONLY { - return llvm::makeArrayRef(MotionModifiers); + return llvm::ArrayRef(MotionModifiers); } /// Fetches ArrayRef of location of motion-modifiers. ArrayRef<SourceLocation> getMotionModifiersLoc() const LLVM_READONLY { - return llvm::makeArrayRef(MotionModifiersLoc); + return llvm::ArrayRef(MotionModifiersLoc); } /// Get colon location. @@ -6994,7 +7297,7 @@ class OMPUseDevicePtrClause final return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } ArrayRef<const Expr *> getPrivateCopies() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); + return llvm::ArrayRef(varlist_end(), varlist_size()); } /// Sets the list of references to initializer variables for new private @@ -7008,7 +7311,7 @@ class OMPUseDevicePtrClause final return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size()); } ArrayRef<const Expr *> getInits() const { - return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size()); + return llvm::ArrayRef(getPrivateCopies().end(), varlist_size()); } public: @@ -7298,6 +7601,110 @@ public: } }; +/// This represents clause 'has_device_ptr' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp target has_device_addr(a,b) +/// \endcode +/// In this example directive '#pragma omp target' has clause +/// 'has_device_ptr' with the variables 'a' and 'b'. +class OMPHasDeviceAddrClause final + : public OMPMappableExprListClause<OMPHasDeviceAddrClause>, + private llvm::TrailingObjects< + OMPHasDeviceAddrClause, Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent> { + friend class OMPClauseReader; + friend OMPMappableExprListClause; + friend OMPVarListClause; + friend TrailingObjects; + + /// Build clause with number of variables \a NumVars. + /// + /// \param Locs Locations needed to build a mappable clause. It includes 1) + /// StartLoc: starting location of the clause (the clause keyword); 2) + /// LParenLoc: location of '('; 3) EndLoc: ending location of the clause. + /// \param Sizes All required sizes to build a mappable clause. It includes 1) + /// NumVars: number of expressions listed in this clause; 2) + /// NumUniqueDeclarations: number of unique base declarations in this clause; + /// 3) NumComponentLists: number of component lists in this clause; and 4) + /// NumComponents: total number of expression components in the clause. + explicit OMPHasDeviceAddrClause(const OMPVarListLocTy &Locs, + const OMPMappableExprListSizeTy &Sizes) + : OMPMappableExprListClause(llvm::omp::OMPC_has_device_addr, Locs, + Sizes) {} + + /// Build an empty clause. + /// + /// \param Sizes All required sizes to build a mappable clause. It includes 1) + /// NumVars: number of expressions listed in this clause; 2) + /// NumUniqueDeclarations: number of unique base declarations in this clause; + /// 3) NumComponentLists: number of component lists in this clause; and 4) + /// NumComponents: total number of expression components in the clause. + explicit OMPHasDeviceAddrClause(const OMPMappableExprListSizeTy &Sizes) + : OMPMappableExprListClause(llvm::omp::OMPC_has_device_addr, + OMPVarListLocTy(), Sizes) {} + + /// Define the sizes of each trailing object array except the last one. This + /// is required for TrailingObjects to work properly. + size_t numTrailingObjects(OverloadToken<Expr *>) const { + return varlist_size(); + } + size_t numTrailingObjects(OverloadToken<ValueDecl *>) const { + return getUniqueDeclarationsNum(); + } + size_t numTrailingObjects(OverloadToken<unsigned>) const { + return getUniqueDeclarationsNum() + getTotalComponentListNum(); + } + +public: + /// Creates clause with a list of variables \a Vars. + /// + /// \param C AST context. + /// \param Locs Locations needed to build a mappable clause. It includes 1) + /// StartLoc: starting location of the clause (the clause keyword); 2) + /// LParenLoc: location of '('; 3) EndLoc: ending location of the clause. + /// \param Vars The original expression used in the clause. + /// \param Declarations Declarations used in the clause. + /// \param ComponentLists Component lists used in the clause. + static OMPHasDeviceAddrClause * + Create(const ASTContext &C, const OMPVarListLocTy &Locs, + ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations, + MappableExprComponentListsRef ComponentLists); + + /// Creates an empty clause with the place for \a NumVars variables. + /// + /// \param C AST context. + /// \param Sizes All required sizes to build a mappable clause. It includes 1) + /// NumVars: number of expressions listed in this clause; 2) + /// NumUniqueDeclarations: number of unique base declarations in this clause; + /// 3) NumComponentLists: number of component lists in this clause; and 4) + /// NumComponents: total number of expression components in the clause. + static OMPHasDeviceAddrClause * + CreateEmpty(const ASTContext &C, const OMPMappableExprListSizeTy &Sizes); + + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + const_child_range children() const { + auto Children = const_cast<OMPHasDeviceAddrClause *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_has_device_addr; + } +}; + /// This represents clause 'nontemporal' in the '#pragma omp ...' directives. /// /// \code @@ -7338,7 +7745,7 @@ class OMPNontemporalClause final return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } ArrayRef<const Expr *> getPrivateRefs() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); + return llvm::ArrayRef(varlist_end(), varlist_size()); } public: @@ -7408,12 +7815,18 @@ class OMPOrderClause final : public OMPClause { /// Location of '('. SourceLocation LParenLoc; - /// A kind of the 'default' clause. + /// A kind of the 'order' clause. OpenMPOrderClauseKind Kind = OMPC_ORDER_unknown; /// Start location of the kind in source code. SourceLocation KindKwLoc; + /// A modifier for order clause + OpenMPOrderClauseModifier Modifier = OMPC_ORDER_MODIFIER_unknown; + + /// Start location of the modifier in source code. + SourceLocation ModifierKwLoc; + /// Set kind of the clause. /// /// \param K Argument of clause. @@ -7424,6 +7837,16 @@ class OMPOrderClause final : public OMPClause { /// \param KLoc Argument location. void setKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } + /// Set modifier of the clause. + /// + /// \param M Argument of clause. + void setModifier(OpenMPOrderClauseModifier M) { Modifier = M; } + + /// Set modifier location. + /// + /// \param MLoc Modifier keyword location. + void setModifierKwLoc(SourceLocation MLoc) { ModifierKwLoc = MLoc; } + public: /// Build 'order' clause with argument \p A ('concurrent'). /// @@ -7432,11 +7855,15 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. + /// \param Modifier The modifier applied to 'order' clause. + /// \param MLoc Location of the modifier OMPOrderClause(OpenMPOrderClauseKind A, SourceLocation ALoc, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) + SourceLocation EndLoc, OpenMPOrderClauseModifier Modifier, + SourceLocation MLoc) : OMPClause(llvm::omp::OMPC_order, StartLoc, EndLoc), - LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc) {} + LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc), Modifier(Modifier), + ModifierKwLoc(MLoc) {} /// Build an empty clause. OMPOrderClause() @@ -7454,6 +7881,12 @@ public: /// Returns location of clause kind. SourceLocation getKindKwLoc() const { return KindKwLoc; } + /// Returns Modifier of the clause. + OpenMPOrderClauseModifier getModifier() const { return Modifier; } + + /// Returns location of clause modifier. + SourceLocation getModifierKwLoc() const { return ModifierKwLoc; } + child_range children() { return child_range(child_iterator(), child_iterator()); } @@ -7528,16 +7961,14 @@ public: /// /// \param C AST context. /// \param InteropVar The interop variable. - /// \param PrefExprs The list of preference expressions. - /// \param IsTarget Uses the 'target' interop-type. - /// \param IsTargetSync Uses the 'targetsync' interop-type. + /// \param InteropInfo The interop-type and prefer_type list. /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param VarLoc Location of the interop variable. /// \param EndLoc Ending location of the clause. static OMPInitClause *Create(const ASTContext &C, Expr *InteropVar, - ArrayRef<Expr *> PrefExprs, bool IsTarget, - bool IsTargetSync, SourceLocation StartLoc, + OMPInteropInfo &InteropInfo, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc); @@ -7764,21 +8195,13 @@ public: /// \endcode /// In this example directive '#pragma omp dispatch' has simple 'novariants' /// clause with condition 'a > 5'. -class OMPNovariantsClause final : public OMPClause, - public OMPClauseWithPreInit { +class OMPNovariantsClause final + : public OMPOneStmtClause<llvm::omp::OMPC_novariants, OMPClause>, + public OMPClauseWithPreInit { friend class OMPClauseReader; - /// Location of '('. - SourceLocation LParenLoc; - - /// Condition of the 'if' clause. - Stmt *Condition = nullptr; - /// Set condition. - void setCondition(Expr *Cond) { Condition = Cond; } - - /// Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + void setCondition(Expr *Cond) { setStmt(Cond); } public: /// Build 'novariants' clause with condition \a Cond. @@ -7794,38 +8217,22 @@ public: OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(llvm::omp::OMPC_novariants, StartLoc, EndLoc), - OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Condition(Cond) { + : OMPOneStmtClause(Cond, StartLoc, LParenLoc, EndLoc), + OMPClauseWithPreInit(this) { setPreInitStmt(HelperCond, CaptureRegion); } /// Build an empty clause. - OMPNovariantsClause() - : OMPClause(llvm::omp::OMPC_novariants, SourceLocation(), - SourceLocation()), - OMPClauseWithPreInit(this) {} - - /// Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } + OMPNovariantsClause() : OMPOneStmtClause(), OMPClauseWithPreInit(this) {} /// Returns condition. - Expr *getCondition() const { return cast_or_null<Expr>(Condition); } - - child_range children() { return child_range(&Condition, &Condition + 1); } - - const_child_range children() const { - return const_child_range(&Condition, &Condition + 1); - } + Expr *getCondition() const { return getStmtAs<Expr>(); } child_range used_children(); const_child_range used_children() const { auto Children = const_cast<OMPNovariantsClause *>(this)->used_children(); return const_child_range(Children.begin(), Children.end()); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_novariants; - } }; /// This represents 'nocontext' clause in the '#pragma omp ...' directive. @@ -7835,20 +8242,13 @@ public: /// \endcode /// In this example directive '#pragma omp dispatch' has simple 'nocontext' /// clause with condition 'a > 5'. -class OMPNocontextClause final : public OMPClause, public OMPClauseWithPreInit { +class OMPNocontextClause final + : public OMPOneStmtClause<llvm::omp::OMPC_nocontext, OMPClause>, + public OMPClauseWithPreInit { friend class OMPClauseReader; - /// Location of '('. - SourceLocation LParenLoc; - - /// Condition of the 'if' clause. - Stmt *Condition = nullptr; - /// Set condition. - void setCondition(Expr *Cond) { Condition = Cond; } - - /// Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + void setCondition(Expr *Cond) { setStmt(Cond); } public: /// Build 'nocontext' clause with condition \a Cond. @@ -7863,38 +8263,22 @@ public: OMPNocontextClause(Expr *Cond, Stmt *HelperCond, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(llvm::omp::OMPC_nocontext, StartLoc, EndLoc), - OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Condition(Cond) { + : OMPOneStmtClause(Cond, StartLoc, LParenLoc, EndLoc), + OMPClauseWithPreInit(this) { setPreInitStmt(HelperCond, CaptureRegion); } /// Build an empty clause. - OMPNocontextClause() - : OMPClause(llvm::omp::OMPC_nocontext, SourceLocation(), - SourceLocation()), - OMPClauseWithPreInit(this) {} - - /// Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } + OMPNocontextClause() : OMPOneStmtClause(), OMPClauseWithPreInit(this) {} /// Returns condition. - Expr *getCondition() const { return cast_or_null<Expr>(Condition); } - - child_range children() { return child_range(&Condition, &Condition + 1); } - - const_child_range children() const { - return const_child_range(&Condition, &Condition + 1); - } + Expr *getCondition() const { return getStmtAs<Expr>(); } child_range used_children(); const_child_range used_children() const { auto Children = const_cast<OMPNocontextClause *>(this)->used_children(); return const_child_range(Children.begin(), Children.end()); } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_nocontext; - } }; /// This represents 'detach' clause in the '#pragma omp task' directive. @@ -7904,20 +8288,12 @@ public: /// \endcode /// In this example directive '#pragma omp detach' has simple 'detach' clause /// with the variable 'evt'. -class OMPDetachClause final : public OMPClause { +class OMPDetachClause final + : public OMPOneStmtClause<llvm::omp::OMPC_detach, OMPClause> { friend class OMPClauseReader; - /// Location of '('. - SourceLocation LParenLoc; - - /// Expression of the 'detach' clause. - Stmt *Evt = nullptr; - /// Set condition. - void setEventHandler(Expr *E) { Evt = E; } - - /// Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + void setEventHandler(Expr *E) { setStmt(E); } public: /// Build 'detach' clause with event-handler \a Evt. @@ -7928,35 +8304,13 @@ public: /// \param EndLoc Ending location of the clause. OMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(llvm::omp::OMPC_detach, StartLoc, EndLoc), - LParenLoc(LParenLoc), Evt(Evt) {} + : OMPOneStmtClause(Evt, StartLoc, LParenLoc, EndLoc) {} /// Build an empty clause. - OMPDetachClause() - : OMPClause(llvm::omp::OMPC_detach, SourceLocation(), SourceLocation()) {} - - /// Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } + OMPDetachClause() : OMPOneStmtClause() {} /// Returns event-handler expression. - Expr *getEventHandler() const { return cast_or_null<Expr>(Evt); } - - child_range children() { return child_range(&Evt, &Evt + 1); } - - const_child_range children() const { - return const_child_range(&Evt, &Evt + 1); - } - - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } - - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_detach; - } + Expr *getEventHandler() const { return getStmtAs<Expr>(); } }; /// This represents clause 'inclusive' in the '#pragma omp scan' directive. @@ -8156,14 +8510,14 @@ private: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - /// \param N Number of allocators asssociated with the clause. + /// \param N Number of allocators associated with the clause. OMPUsesAllocatorsClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) : OMPClause(llvm::omp::OMPC_uses_allocators, StartLoc, EndLoc), LParenLoc(LParenLoc), NumOfAllocators(N) {} /// Build an empty clause. - /// \param N Number of allocators asssociated with the clause. + /// \param N Number of allocators associated with the clause. /// explicit OMPUsesAllocatorsClause(unsigned N) : OMPClause(llvm::omp::OMPC_uses_allocators, SourceLocation(), @@ -8257,14 +8611,14 @@ class OMPAffinityClause final /// \param LParenLoc Location of '('. /// \param ColonLoc Location of ':'. /// \param EndLoc Ending location of the clause. - /// \param N Number of locators asssociated with the clause. + /// \param N Number of locators associated with the clause. OMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N) : OMPVarListClause<OMPAffinityClause>(llvm::omp::OMPC_affinity, StartLoc, LParenLoc, EndLoc, N) {} /// Build an empty clause. - /// \param N Number of locators asssociated with the clause. + /// \param N Number of locators associated with the clause. /// explicit OMPAffinityClause(unsigned N) : OMPVarListClause<OMPAffinityClause>(llvm::omp::OMPC_affinity, @@ -8340,20 +8694,13 @@ public: /// \endcode /// In this example directive '#pragma omp masked' has 'filter' clause with /// thread id. -class OMPFilterClause final : public OMPClause, public OMPClauseWithPreInit { +class OMPFilterClause final + : public OMPOneStmtClause<llvm::omp::OMPC_filter, OMPClause>, + public OMPClauseWithPreInit { friend class OMPClauseReader; - /// Location of '('. - SourceLocation LParenLoc; - - /// Express of the 'filter' clause. - Stmt *ThreadID = nullptr; - /// Sets the thread identifier. - void setThreadID(Expr *TID) { ThreadID = TID; } - - /// Sets the location of '('. - void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + void setThreadID(Expr *TID) { setStmt(TID); } public: /// Build 'filter' clause with thread-id \a ThreadID. @@ -8368,40 +8715,89 @@ public: OMPFilterClause(Expr *ThreadID, Stmt *HelperE, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(llvm::omp::OMPC_filter, StartLoc, EndLoc), - OMPClauseWithPreInit(this), LParenLoc(LParenLoc), ThreadID(ThreadID) { + : OMPOneStmtClause(ThreadID, StartLoc, LParenLoc, EndLoc), + OMPClauseWithPreInit(this) { setPreInitStmt(HelperE, CaptureRegion); } /// Build an empty clause. - OMPFilterClause() - : OMPClause(llvm::omp::OMPC_filter, SourceLocation(), SourceLocation()), - OMPClauseWithPreInit(this) {} - /// Returns the location of '('. - SourceLocation getLParenLoc() const { return LParenLoc; } + OMPFilterClause() : OMPOneStmtClause(), OMPClauseWithPreInit(this) {} /// Return thread identifier. - Expr *getThreadID() { return cast<Expr>(ThreadID); } + Expr *getThreadID() const { return getStmtAs<Expr>(); } /// Return thread identifier. - Expr *getThreadID() const { return cast<Expr>(ThreadID); } + Expr *getThreadID() { return getStmtAs<Expr>(); } +}; + +/// This represents 'bind' clause in the '#pragma omp ...' directives. +/// +/// \code +/// #pragma omp loop bind(parallel) +/// \endcode +class OMPBindClause final : public OMPNoChildClause<llvm::omp::OMPC_bind> { + friend class OMPClauseReader; - child_range children() { return child_range(&ThreadID, &ThreadID + 1); } + /// Location of '('. + SourceLocation LParenLoc; - const_child_range children() const { - return const_child_range(&ThreadID, &ThreadID + 1); - } + /// The binding kind of 'bind' clause. + OpenMPBindClauseKind Kind = OMPC_BIND_unknown; - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } + /// Start location of the kind in source code. + SourceLocation KindLoc; - static bool classof(const OMPClause *T) { - return T->getClauseKind() == llvm::omp::OMPC_filter; - } + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + + /// Set the binding kind. + void setBindKind(OpenMPBindClauseKind K) { Kind = K; } + + /// Set the binding kind location. + void setBindKindLoc(SourceLocation KLoc) { KindLoc = KLoc; } + + /// Build 'bind' clause with kind \a K ('teams', 'parallel', or 'thread'). + /// + /// \param K Binding kind of the clause ('teams', 'parallel' or 'thread'). + /// \param KLoc Starting location of the binding kind. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + OMPBindClause(OpenMPBindClauseKind K, SourceLocation KLoc, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPNoChildClause(StartLoc, EndLoc), LParenLoc(LParenLoc), Kind(K), + KindLoc(KLoc) {} + + /// Build an empty clause. + OMPBindClause() : OMPNoChildClause() {} + +public: + /// Build 'bind' clause with kind \a K ('teams', 'parallel', or 'thread'). + /// + /// \param C AST context + /// \param K Binding kind of the clause ('teams', 'parallel' or 'thread'). + /// \param KLoc Starting location of the binding kind. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + static OMPBindClause *Create(const ASTContext &C, OpenMPBindClauseKind K, + SourceLocation KLoc, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc); + + /// Build an empty 'bind' clause. + /// + /// \param C AST context + static OMPBindClause *CreateEmpty(const ASTContext &C); + + /// Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// Returns kind of the clause. + OpenMPBindClauseKind getBindKind() const { return Kind; } + + /// Returns location of clause kind. + SourceLocation getBindKindLoc() const { return KindLoc; } }; /// This class implements a simple visitor for OMPClause @@ -8546,10 +8942,11 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo *TI); /// Clang specific specialization of the OMPContext to lookup target features. struct TargetOMPContext final : public llvm::omp::OMPContext { - TargetOMPContext(ASTContext &ASTCtx, std::function<void(StringRef)> &&DiagUnknownTrait, - const FunctionDecl *CurrentFunctionDecl); + const FunctionDecl *CurrentFunctionDecl, + ArrayRef<llvm::omp::TraitProperty> ConstructTraits); + virtual ~TargetOMPContext() = default; /// See llvm::omp::OMPContext::matchesISATrait @@ -8630,7 +9027,7 @@ public: /// Get the clauses storage. MutableArrayRef<OMPClause *> getClauses() { - return llvm::makeMutableArrayRef(getTrailingObjects<OMPClause *>(), + return llvm::MutableArrayRef(getTrailingObjects<OMPClause *>(), NumClauses); } ArrayRef<OMPClause *> getClauses() const { @@ -8644,9 +9041,7 @@ public: const CapturedStmt * getCapturedStmt(OpenMPDirectiveKind RegionKind, ArrayRef<OpenMPDirectiveKind> CaptureRegions) const { - assert(llvm::any_of( - CaptureRegions, - [=](const OpenMPDirectiveKind K) { return K == RegionKind; }) && + assert(llvm::is_contained(CaptureRegions, RegionKind) && "RegionKind not found in OpenMP CaptureRegions."); auto *CS = cast<CapturedStmt>(getAssociatedStmt()); for (auto ThisCaptureRegion : CaptureRegions) { @@ -8705,6 +9100,243 @@ public: } }; +/// This represents 'ompx_dyn_cgroup_mem' clause in the '#pragma omp target ...' +/// directive. +/// +/// \code +/// #pragma omp target [...] ompx_dyn_cgroup_mem(N) +/// \endcode +class OMPXDynCGroupMemClause + : public OMPOneStmtClause<llvm::omp::OMPC_ompx_dyn_cgroup_mem, OMPClause>, + public OMPClauseWithPreInit { + friend class OMPClauseReader; + + /// Set size. + void setSize(Expr *E) { setStmt(E); } + +public: + /// Build 'ompx_dyn_cgroup_mem' clause. + /// + /// \param Size Size expression. + /// \param HelperSize Helper Size expression + /// \param CaptureRegion Innermost OpenMP region where expressions in this + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + OMPXDynCGroupMemClause(Expr *Size, Stmt *HelperSize, + OpenMPDirectiveKind CaptureRegion, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPOneStmtClause(Size, StartLoc, LParenLoc, EndLoc), + OMPClauseWithPreInit(this) { + setPreInitStmt(HelperSize, CaptureRegion); + } + + /// Build an empty clause. + OMPXDynCGroupMemClause() : OMPOneStmtClause(), OMPClauseWithPreInit(this) {} + + /// Return the size expression. + Expr *getSize() { return getStmtAs<Expr>(); } + + /// Return the size expression. + Expr *getSize() const { return getStmtAs<Expr>(); } +}; + +/// This represents the 'doacross' clause for the '#pragma omp ordered' +/// directive. +/// +/// \code +/// #pragma omp ordered doacross(sink: i-1, j-1) +/// \endcode +/// In this example directive '#pragma omp ordered' with clause 'doacross' with +/// a dependence-type 'sink' and loop-iteration vector expressions i-1 and j-1. +class OMPDoacrossClause final + : public OMPVarListClause<OMPDoacrossClause>, + private llvm::TrailingObjects<OMPDoacrossClause, Expr *> { + friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + + /// Dependence type (sink or source). + OpenMPDoacrossClauseModifier DepType = OMPC_DOACROSS_unknown; + + /// Dependence type location. + SourceLocation DepLoc; + + /// Colon location. + SourceLocation ColonLoc; + + /// Number of loops, associated with the doacross clause. + unsigned NumLoops = 0; + + /// Build clause with number of expressions \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of expressions in the clause. + /// \param NumLoops Number of loops associated with the clause. + OMPDoacrossClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N, unsigned NumLoops) + : OMPVarListClause<OMPDoacrossClause>(llvm::omp::OMPC_doacross, StartLoc, + LParenLoc, EndLoc, N), + NumLoops(NumLoops) {} + + /// Build an empty clause. + /// + /// \param N Number of expressions in the clause. + /// \param NumLoops Number of loops associated with the clause. + explicit OMPDoacrossClause(unsigned N, unsigned NumLoops) + : OMPVarListClause<OMPDoacrossClause>(llvm::omp::OMPC_doacross, + SourceLocation(), SourceLocation(), + SourceLocation(), N), + NumLoops(NumLoops) {} + + /// Set dependence type. + void setDependenceType(OpenMPDoacrossClauseModifier M) { DepType = M; } + + /// Set dependence type location. + void setDependenceLoc(SourceLocation Loc) { DepLoc = Loc; } + + /// Set colon location. + void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + +public: + /// Creates clause with a list of expressions \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param DepType The dependence type. + /// \param DepLoc Location of the dependence type. + /// \param ColonLoc Location of ':'. + /// \param VL List of references to the expressions. + /// \param NumLoops Number of loops that associated with the clause. + static OMPDoacrossClause * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, OpenMPDoacrossClauseModifier DepType, + SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL, + unsigned NumLoops); + + /// Creates an empty clause with \a N expressions. + /// + /// \param C AST context. + /// \param N The number of expressions. + /// \param NumLoops Number of loops that is associated with this clause. + static OMPDoacrossClause *CreateEmpty(const ASTContext &C, unsigned N, + unsigned NumLoops); + + /// Get dependence type. + OpenMPDoacrossClauseModifier getDependenceType() const { return DepType; } + + /// Get dependence type location. + SourceLocation getDependenceLoc() const { return DepLoc; } + + /// Get colon location. + SourceLocation getColonLoc() const { return ColonLoc; } + + /// Get number of loops associated with the clause. + unsigned getNumLoops() const { return NumLoops; } + + /// Set the loop data. + void setLoopData(unsigned NumLoop, Expr *Cnt); + + /// Get the loop data. + Expr *getLoopData(unsigned NumLoop); + const Expr *getLoopData(unsigned NumLoop) const; + + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + const_child_range children() const { + auto Children = const_cast<OMPDoacrossClause *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_doacross; + } +}; + +/// This represents 'ompx_attribute' clause in a directive that might generate +/// an outlined function. An example is given below. +/// +/// \code +/// #pragma omp target [...] ompx_attribute(flatten) +/// \endcode +class OMPXAttributeClause + : public OMPNoChildClause<llvm::omp::OMPC_ompx_attribute> { + friend class OMPClauseReader; + + /// Location of '('. + SourceLocation LParenLoc; + + /// The parsed attributes (clause arguments) + SmallVector<const Attr *> Attrs; + +public: + /// Build 'ompx_attribute' clause. + /// + /// \param Attrs The parsed attributes (clause arguments) + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + OMPXAttributeClause(ArrayRef<const Attr *> Attrs, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OMPNoChildClause(StartLoc, EndLoc), LParenLoc(LParenLoc), Attrs(Attrs) { + } + + /// Build an empty clause. + OMPXAttributeClause() : OMPNoChildClause() {} + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + + /// Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// Returned the attributes parsed from this clause. + ArrayRef<const Attr *> getAttrs() const { return Attrs; } + +private: + /// Replace the attributes with \p NewAttrs. + void setAttrs(ArrayRef<Attr *> NewAttrs) { + Attrs.clear(); + Attrs.append(NewAttrs.begin(), NewAttrs.end()); + } +}; + +/// This represents 'ompx_bare' clause in the '#pragma omp target teams ...' +/// directive. +/// +/// \code +/// #pragma omp target teams ompx_bare +/// \endcode +/// In this example directive '#pragma omp target teams' has a 'ompx_bare' +/// clause. +class OMPXBareClause : public OMPNoChildClause<llvm::omp::OMPC_ompx_bare> { +public: + /// Build 'ompx_bare' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + OMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPNoChildClause(StartLoc, EndLoc) {} + + /// Build an empty clause. + OMPXBareClause() = default; +}; + } // namespace clang #endif // LLVM_CLANG_AST_OPENMPCLAUSE_H diff --git a/contrib/llvm-project/clang/include/clang/AST/OperationKinds.def b/contrib/llvm-project/clang/include/clang/AST/OperationKinds.def index b05b9d81569e..8dd98730dff7 100644 --- a/contrib/llvm-project/clang/include/clang/AST/OperationKinds.def +++ b/contrib/llvm-project/clang/include/clang/AST/OperationKinds.def @@ -80,6 +80,7 @@ CAST_OPERATION(LValueToRValue) /// (possibly) adding qualifiers or removing noexcept. /// int -> int /// char** -> const char * const * +/// int[1] -> int[] /// void () noexcept -> void () CAST_OPERATION(NoOp) @@ -362,8 +363,8 @@ CAST_OPERATION(IntToOCLSampler) //===- Binary Operations -------------------------------------------------===// // Operators listed in order of precedence. -// Note that additions to this should also update the StmtVisitor class and -// BinaryOperator::getOverloadedOperator. +// Note that additions to this should also update the StmtVisitor class, +// BinaryOperator::getOverloadedOperator and CXBinaryOperatorKind enum. // [C++ 5.5] Pointer-to-member operators. BINARY_OPERATION(PtrMemD, ".*") @@ -415,8 +416,8 @@ BINARY_OPERATION(Comma, ",") //===- Unary Operations ---------------------------------------------------===// -// Note that additions to this should also update the StmtVisitor class and -// UnaryOperator::getOverloadedOperator. +// Note that additions to this should also update the StmtVisitor class, +// UnaryOperator::getOverloadedOperator and CXUnaryOperatorKind enum. // [C99 6.5.2.4] Postfix increment and decrement UNARY_OPERATION(PostInc, "++") diff --git a/contrib/llvm-project/clang/include/clang/AST/ParentMapContext.h b/contrib/llvm-project/clang/include/clang/AST/ParentMapContext.h index 2edbc987850d..d3b2e3986a99 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ParentMapContext.h +++ b/contrib/llvm-project/clang/include/clang/AST/ParentMapContext.h @@ -77,7 +77,7 @@ class TraversalKindScope { TraversalKind TK = TK_AsIs; public: - TraversalKindScope(ASTContext &ASTCtx, llvm::Optional<TraversalKind> ScopeTK) + TraversalKindScope(ASTContext &ASTCtx, std::optional<TraversalKind> ScopeTK) : Ctx(ASTCtx.getParentMapContext()) { TK = Ctx.getTraversalKind(); if (ScopeTK) @@ -90,29 +90,27 @@ public: /// Container for either a single DynTypedNode or for an ArrayRef to /// DynTypedNode. For use with ParentMap. class DynTypedNodeList { - llvm::AlignedCharArrayUnion<DynTypedNode, ArrayRef<DynTypedNode>> Storage; + union { + DynTypedNode SingleNode; + ArrayRef<DynTypedNode> Nodes; + }; bool IsSingleNode; public: DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) { - new (&Storage) DynTypedNode(N); + new (&SingleNode) DynTypedNode(N); } DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) { - new (&Storage) ArrayRef<DynTypedNode>(A); + new (&Nodes) ArrayRef<DynTypedNode>(A); } const DynTypedNode *begin() const { - if (!IsSingleNode) - return reinterpret_cast<const ArrayRef<DynTypedNode> *>(&Storage) - ->begin(); - return reinterpret_cast<const DynTypedNode *>(&Storage); + return !IsSingleNode ? Nodes.begin() : &SingleNode; } const DynTypedNode *end() const { - if (!IsSingleNode) - return reinterpret_cast<const ArrayRef<DynTypedNode> *>(&Storage)->end(); - return reinterpret_cast<const DynTypedNode *>(&Storage) + 1; + return !IsSingleNode ? Nodes.end() : &SingleNode + 1; } size_t size() const { return end() - begin(); } diff --git a/contrib/llvm-project/clang/include/clang/AST/PrettyDeclStackTrace.h b/contrib/llvm-project/clang/include/clang/AST/PrettyDeclStackTrace.h index 899bbcb3be45..82df031d4126 100644 --- a/contrib/llvm-project/clang/include/clang/AST/PrettyDeclStackTrace.h +++ b/contrib/llvm-project/clang/include/clang/AST/PrettyDeclStackTrace.h @@ -22,7 +22,6 @@ namespace clang { class ASTContext; class Decl; -class SourceManager; /// PrettyDeclStackTraceEntry - If a crash occurs in the parser while /// parsing something related to a declaration, include that diff --git a/contrib/llvm-project/clang/include/clang/AST/PrettyPrinter.h b/contrib/llvm-project/clang/include/clang/AST/PrettyPrinter.h index 3baf2b2ba94d..da276e26049b 100644 --- a/contrib/llvm-project/clang/include/clang/AST/PrettyPrinter.h +++ b/contrib/llvm-project/clang/include/clang/AST/PrettyPrinter.h @@ -20,9 +20,7 @@ namespace clang { class DeclContext; class LangOptions; -class SourceManager; class Stmt; -class TagDecl; class PrinterHelper { public: @@ -62,19 +60,24 @@ struct PrintingPolicy { : Indentation(2), SuppressSpecifiers(false), SuppressTagKeyword(LO.CPlusPlus), IncludeTagDefinition(false), SuppressScope(false), SuppressUnwrittenScope(false), - SuppressInlineNamespace(true), SuppressInitializers(false), - ConstantArraySizeAsWritten(false), AnonymousTagLocations(true), - SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false), + SuppressInlineNamespace(true), SuppressElaboration(false), + SuppressInitializers(false), ConstantArraySizeAsWritten(false), + AnonymousTagLocations(true), SuppressStrongLifetime(false), + SuppressLifetimeQualifiers(false), SuppressTemplateArgsInCXXConstructors(false), SuppressDefaultTemplateArgs(true), Bool(LO.Bool), - Nullptr(LO.CPlusPlus11), Restrict(LO.C99), Alignof(LO.CPlusPlus11), - UnderscoreAlignof(LO.C11), UseVoidForZeroParams(!LO.CPlusPlus), + Nullptr(LO.CPlusPlus11 || LO.C23), NullptrTypeInNamespace(LO.CPlusPlus), + Restrict(LO.C99), Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11), + UseVoidForZeroParams(!LO.CPlusPlus), SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false), PolishForDeclaration(false), Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), MSVCFormatting(false), ConstantsAsWritten(false), SuppressImplicitBase(false), FullyQualifiedName(false), - PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true) {} + PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true), + UsePreferredNames(true), AlwaysIncludeTypeForTemplateArgument(false), + CleanUglifiedParameters(false), EntireContentsOfLargeArray(true), + UseEnumerators(true) {} /// Adjust this printing policy for cases where it's known that we're /// printing C++ code (for instance, if AST dumping reaches a C++-only @@ -103,6 +106,7 @@ struct PrintingPolicy { /// declaration for "x", so that we will print "int *x"; it will be /// \c true when we print "y", so that we suppress printing the /// "const int" type specifier and instead only print the "*y". + LLVM_PREFERRED_TYPE(bool) unsigned SuppressSpecifiers : 1; /// Whether type printing should skip printing the tag keyword. @@ -113,6 +117,7 @@ struct PrintingPolicy { /// \code /// struct Geometry::Point; /// \endcode + LLVM_PREFERRED_TYPE(bool) unsigned SuppressTagKeyword : 1; /// When true, include the body of a tag definition. @@ -123,20 +128,29 @@ struct PrintingPolicy { /// \code /// typedef struct { int x, y; } Point; /// \endcode + LLVM_PREFERRED_TYPE(bool) unsigned IncludeTagDefinition : 1; /// Suppresses printing of scope specifiers. + LLVM_PREFERRED_TYPE(bool) unsigned SuppressScope : 1; /// Suppress printing parts of scope specifiers that are never /// written, e.g., for anonymous namespaces. + LLVM_PREFERRED_TYPE(bool) unsigned SuppressUnwrittenScope : 1; /// Suppress printing parts of scope specifiers that correspond /// to inline namespaces, where the name is unambiguous with the specifier /// removed. + LLVM_PREFERRED_TYPE(bool) unsigned SuppressInlineNamespace : 1; + /// Ignore qualifiers and tag keywords as specified by elaborated type sugar, + /// instead letting the underlying type print as normal. + LLVM_PREFERRED_TYPE(bool) + unsigned SuppressElaboration : 1; + /// Suppress printing of variable initializers. /// /// This flag is used when printing the loop variable in a for-range @@ -148,6 +162,7 @@ struct PrintingPolicy { /// /// SuppressInitializers will be true when printing "auto x", so that the /// internal initializer constructed for x will not be printed. + LLVM_PREFERRED_TYPE(bool) unsigned SuppressInitializers : 1; /// Whether we should print the sizes of constant array expressions as written @@ -166,50 +181,67 @@ struct PrintingPolicy { /// int a[104]; /// char a[9] = "A string"; /// \endcode + LLVM_PREFERRED_TYPE(bool) unsigned ConstantArraySizeAsWritten : 1; /// When printing an anonymous tag name, also print the location of that /// entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just prints /// "(anonymous)" for the name. + LLVM_PREFERRED_TYPE(bool) unsigned AnonymousTagLocations : 1; /// When true, suppress printing of the __strong lifetime qualifier in ARC. + LLVM_PREFERRED_TYPE(bool) unsigned SuppressStrongLifetime : 1; /// When true, suppress printing of lifetime qualifier in ARC. + LLVM_PREFERRED_TYPE(bool) unsigned SuppressLifetimeQualifiers : 1; /// When true, suppresses printing template arguments in names of C++ /// constructors. + LLVM_PREFERRED_TYPE(bool) unsigned SuppressTemplateArgsInCXXConstructors : 1; /// When true, attempt to suppress template arguments that match the default /// argument for the parameter. + LLVM_PREFERRED_TYPE(bool) unsigned SuppressDefaultTemplateArgs : 1; /// Whether we can use 'bool' rather than '_Bool' (even if the language /// doesn't actually have 'bool', because, e.g., it is defined as a macro). + LLVM_PREFERRED_TYPE(bool) unsigned Bool : 1; /// Whether we should use 'nullptr' rather than '0' as a null pointer /// constant. + LLVM_PREFERRED_TYPE(bool) unsigned Nullptr : 1; + /// Whether 'nullptr_t' is in namespace 'std' or not. + LLVM_PREFERRED_TYPE(bool) + unsigned NullptrTypeInNamespace : 1; + /// Whether we can use 'restrict' rather than '__restrict'. + LLVM_PREFERRED_TYPE(bool) unsigned Restrict : 1; /// Whether we can use 'alignof' rather than '__alignof'. + LLVM_PREFERRED_TYPE(bool) unsigned Alignof : 1; /// Whether we can use '_Alignof' rather than '__alignof'. + LLVM_PREFERRED_TYPE(bool) unsigned UnderscoreAlignof : 1; /// Whether we should use '(void)' rather than '()' for a function prototype /// with zero parameters. + LLVM_PREFERRED_TYPE(bool) unsigned UseVoidForZeroParams : 1; /// Whether nested templates must be closed like 'a\<b\<c\> \>' rather than /// 'a\<b\<c\>\>'. + LLVM_PREFERRED_TYPE(bool) unsigned SplitTemplateClosers : 1; /// Provide a 'terse' output. @@ -217,27 +249,33 @@ struct PrintingPolicy { /// For example, in this mode we don't print function bodies, class members, /// declarations inside namespaces etc. Effectively, this should print /// only the requested declaration. + LLVM_PREFERRED_TYPE(bool) unsigned TerseOutput : 1; /// When true, do certain refinement needed for producing proper declaration /// tag; such as, do not print attributes attached to the declaration. /// + LLVM_PREFERRED_TYPE(bool) unsigned PolishForDeclaration : 1; /// When true, print the half-precision floating-point type as 'half' /// instead of '__fp16' + LLVM_PREFERRED_TYPE(bool) unsigned Half : 1; /// When true, print the built-in wchar_t type as __wchar_t. For use in /// Microsoft mode when wchar_t is not available. + LLVM_PREFERRED_TYPE(bool) unsigned MSWChar : 1; /// When true, include newlines after statements like "break", etc. + LLVM_PREFERRED_TYPE(bool) unsigned IncludeNewlines : 1; /// Use whitespace and punctuation like MSVC does. In particular, this prints /// anonymous namespaces as `anonymous namespace' and does not insert spaces /// after template arguments. + LLVM_PREFERRED_TYPE(bool) unsigned MSVCFormatting : 1; /// Whether we should print the constant expressions as written in the @@ -256,23 +294,54 @@ struct PrintingPolicy { /// 0x10 /// 2.5e3 /// \endcode + LLVM_PREFERRED_TYPE(bool) unsigned ConstantsAsWritten : 1; /// When true, don't print the implicit 'self' or 'this' expressions. + LLVM_PREFERRED_TYPE(bool) unsigned SuppressImplicitBase : 1; /// When true, print the fully qualified name of function declarations. /// This is the opposite of SuppressScope and thus overrules it. + LLVM_PREFERRED_TYPE(bool) unsigned FullyQualifiedName : 1; /// Whether to print types as written or canonically. + LLVM_PREFERRED_TYPE(bool) unsigned PrintCanonicalTypes : 1; /// Whether to print an InjectedClassNameType with template arguments or as /// written. When a template argument is unnamed, printing it results in /// invalid C++ code. + LLVM_PREFERRED_TYPE(bool) unsigned PrintInjectedClassNameWithArguments : 1; + /// Whether to use C++ template preferred_name attributes when printing + /// templates. + LLVM_PREFERRED_TYPE(bool) + unsigned UsePreferredNames : 1; + + /// Whether to use type suffixes (eg: 1U) on integral non-type template + /// parameters. + LLVM_PREFERRED_TYPE(bool) + unsigned AlwaysIncludeTypeForTemplateArgument : 1; + + /// Whether to strip underscores when printing reserved parameter names. + /// e.g. std::vector<class _Tp> becomes std::vector<class Tp>. + /// This only affects parameter names, and so describes a compatible API. + LLVM_PREFERRED_TYPE(bool) + unsigned CleanUglifiedParameters : 1; + + /// Whether to print the entire array initializers, especially on non-type + /// template parameters, no matter how many elements there are. + LLVM_PREFERRED_TYPE(bool) + unsigned EntireContentsOfLargeArray : 1; + + /// Whether to print enumerator non-type template parameters with a matching + /// enumerator name or via cast of an integer. + LLVM_PREFERRED_TYPE(bool) + unsigned UseEnumerators : 1; + /// Callbacks to use to allow the behavior of printing to be customized. const PrintingCallbacks *Callbacks = nullptr; }; diff --git a/contrib/llvm-project/clang/include/clang/AST/PropertiesBase.td b/contrib/llvm-project/clang/include/clang/AST/PropertiesBase.td index a087cb406b29..0270c086d06b 100644 --- a/contrib/llvm-project/clang/include/clang/AST/PropertiesBase.td +++ b/contrib/llvm-project/clang/include/clang/AST/PropertiesBase.td @@ -41,7 +41,7 @@ class RefPropertyType<string className> : PropertyType<className # "*"> { let PackOptional = "value ? *value : nullptr"; let UnpackOptional = - "value ? llvm::Optional<" # CXXName # ">(value) : llvm::None"; + "value ? std::optional<" # CXXName # ">(value) : std::nullopt"; } /// Property types that correspond to a specific subclass of another type. @@ -58,7 +58,7 @@ class DefaultValuePropertyType<string typeName = ""> : PropertyType<typeName> { let PackOptional = "value ? *value : " # CXXName # "()"; let UnpackOptional = - "value.isNull() ? llvm::None : llvm::Optional<" # CXXName # ">(value)"; + "value.isNull() ? std::nullopt : std::optional<" # CXXName # ">(value)"; } /// Property types that correspond to integer types and support optional @@ -67,18 +67,19 @@ class CountPropertyType<string typeName = ""> : PropertyType<typeName> { let PackOptional = "value ? *value + 1 : 0"; let UnpackOptional = - "value ? llvm::Optional<" # CXXName # ">(value - 1) : llvm::None"; + "value ? std::optional<" # CXXName # ">(value - 1) : std::nullopt"; } def APInt : PropertyType<"llvm::APInt"> { let PassByReference = 1; } def APSInt : PropertyType<"llvm::APSInt"> { let PassByReference = 1; } def APValue : PropertyType { let PassByReference = 1; } def APValueKind : EnumPropertyType<"APValue::ValueKind">; -def ArraySizeModifier : EnumPropertyType<"ArrayType::ArraySizeModifier">; +def ArraySizeModifier : EnumPropertyType<"ArraySizeModifier">; def AttrKind : EnumPropertyType<"attr::Kind">; def AutoTypeKeyword : EnumPropertyType; def Bool : PropertyType<"bool">; def BuiltinTypeKind : EnumPropertyType<"BuiltinType::Kind">; +def BTFTypeTagAttr : PropertyType<"const BTFTypeTagAttr *">; def CallingConv : EnumPropertyType; def DeclarationName : PropertyType; def DeclarationNameKind : EnumPropertyType<"DeclarationName::NameKind">; @@ -107,6 +108,8 @@ def DeclRef : RefPropertyType<"Decl"> { let ConstWhenWriting = 1; } SubclassPropertyType<"TemplateTypeParmDecl", DeclRef>; def TemplateTemplateParmDeclRef : SubclassPropertyType<"TemplateTemplateParmDecl", DeclRef>; + def UsingShadowDeclRef : + SubclassPropertyType<"UsingShadowDecl", DeclRef>; def ValueDeclRef : SubclassPropertyType<"ValueDecl", DeclRef>; def ElaboratedTypeKeyword : EnumPropertyType; @@ -135,10 +138,11 @@ def TemplateArgument : PropertyType; def TemplateArgumentKind : EnumPropertyType<"TemplateArgument::ArgKind">; def TemplateName : DefaultValuePropertyType; def TemplateNameKind : EnumPropertyType<"TemplateName::NameKind">; +def TypeOfKind : EnumPropertyType<"TypeOfKind">; def UInt32 : CountPropertyType<"uint32_t">; def UInt64 : CountPropertyType<"uint64_t">; def UnaryTypeTransformKind : EnumPropertyType<"UnaryTransformType::UTTKind">; -def VectorKind : EnumPropertyType<"VectorType::VectorKind">; +def VectorKind : EnumPropertyType<"VectorKind">; def ExceptionSpecInfo : PropertyType<"FunctionProtoType::ExceptionSpecInfo"> { let BufferElementTypes = [ QualType ]; @@ -151,7 +155,7 @@ class Array<PropertyType element> : PropertyType { let BufferElementTypes = [ element ]; } -/// llvm::Optional<T>. The corresponding C++ type is generally just the +/// std::optional<T>. The corresponding C++ type is generally just the /// corresponding C++ type of the element. /// /// Optional<Unsigned> may restrict the range of the operand for some @@ -446,10 +450,13 @@ let Class = PropertyTypeCase<APValue, "LValue"> in { lvalueBase ? lvalueBase.dyn_cast<const Expr *>() : nullptr; bool lvalueBaseIsExpr = (bool) expr; bool lvalueBaseIsTypeInfo = lvalueBase.is<TypeInfoLValue>(); + bool lvalueBaseIsDynamicAlloc = lvalueBase.is<DynamicAllocLValue>(); QualType elemTy; if (lvalueBase) { if (lvalueBaseIsTypeInfo) { elemTy = lvalueBase.getTypeInfoType(); + } else if (lvalueBaseIsDynamicAlloc) { + elemTy = lvalueBase.getDynamicAllocType(); } else if (lvalueBaseIsExpr) { elemTy = expr->getType(); } else { @@ -469,6 +476,9 @@ let Class = PropertyTypeCase<APValue, "LValue"> in { def : Property<"isTypeInfo", Bool> { let Read = [{ lvalueBaseIsTypeInfo }]; } + def : Property<"isDynamicAlloc", Bool> { + let Read = [{ lvalueBaseIsDynamicAlloc }]; + } def : Property<"hasBase", Bool> { let Read = [{ static_cast<bool>(lvalueBase) }]; } @@ -481,9 +491,17 @@ let Class = PropertyTypeCase<APValue, "LValue"> in { QualType(node.getLValueBase().get<TypeInfoLValue>().getType(), 0) }]; } + def : Property<"dynamicAlloc", UInt32> { + let Conditional = [{ hasBase && isDynamicAlloc }]; + let Read = [{ node.getLValueBase().get<DynamicAllocLValue>().getIndex() }]; + } def : Property<"type", QualType> { - let Conditional = [{ hasBase && isTypeInfo }]; - let Read = [{ node.getLValueBase().getTypeInfoType() }]; + let Conditional = [{ hasBase && (isTypeInfo || isDynamicAlloc) }]; + let Read = [{ + isTypeInfo + ? node.getLValueBase().getTypeInfoType() + : node.getLValueBase().getDynamicAllocType() + }]; } def : Property<"callIndex", UInt32> { let Conditional = [{ hasBase && !isTypeInfo }]; @@ -498,7 +516,7 @@ let Class = PropertyTypeCase<APValue, "LValue"> in { let Read = [{ const_cast<Expr *>(expr) }]; } def : Property<"decl", DeclRef> { - let Conditional = [{ hasBase && !isTypeInfo && !isExpr }]; + let Conditional = [{ hasBase && !isTypeInfo && !isDynamicAlloc && !isExpr }]; let Read = [{ lvalueBase.get<const ValueDecl *>() }]; } def : Property<"offsetQuantity", UInt32> { @@ -513,20 +531,19 @@ let Class = PropertyTypeCase<APValue, "LValue"> in { def : Creator<[{ (void)ctx; APValue::LValueBase base; - QualType elemTy; if (hasBase) { if (isTypeInfo) { base = APValue::LValueBase::getTypeInfo( - TypeInfoLValue(typeInfo.getValue().getTypePtr()), type.getValue()); - elemTy = base.getTypeInfoType(); + TypeInfoLValue(typeInfo->getTypePtr()), *type); + } else if (isDynamicAlloc) { + base = APValue::LValueBase::getDynamicAlloc( + DynamicAllocLValue(*dynamicAlloc), *type); } else if (isExpr) { - base = APValue::LValueBase(cast<Expr>(stmt.getValue()), - callIndex.getValue(), version.getValue()); - elemTy = base.get<const Expr *>()->getType(); + base = APValue::LValueBase(cast<Expr>(*stmt), + *callIndex, *version); } else { - base = APValue::LValueBase(cast<ValueDecl>(decl.getValue()), - callIndex.getValue(), version.getValue()); - elemTy = base.get<const ValueDecl *>()->getType(); + base = APValue::LValueBase(cast<ValueDecl>(*decl), + *callIndex, *version); } } CharUnits offset = CharUnits::fromQuantity(offsetQuantity); @@ -539,7 +556,6 @@ let Class = PropertyTypeCase<APValue, "LValue"> in { auto pathLength = lvaluePath->Path.size(); APValue::LValuePathEntry *path = result.setLValueUninit( base, offset, pathLength, isLValueOnePastTheEnd, isNullPtr).data(); - assert(lvaluePath->getType() == elemTy && "Unexpected type reference!"); llvm::copy(lvaluePath->Path, path); return result; }]>; @@ -617,6 +633,16 @@ let Class = PropertyTypeCase<TemplateName, "Template"> in { return TemplateName(declaration); }]>; } + +let Class = PropertyTypeCase<TemplateName, "UsingTemplate"> in { + def : Property<"foundDecl", UsingShadowDeclRef> { + let Read = [{ node.getAsUsingShadowDecl() }]; + } + def : Creator<[{ + return TemplateName(foundDecl); + }]>; +} + let Class = PropertyTypeCase<TemplateName, "OverloadedTemplate"> in { def : Property<"overloads", Array<NamedDeclRef>> { let Read = [{ node.getAsOverloadedTemplate()->decls() }]; @@ -650,12 +676,12 @@ let Class = PropertyTypeCase<TemplateName, "QualifiedTemplate"> in { def : Property<"hasTemplateKeyword", Bool> { let Read = [{ qtn->hasTemplateKeyword() }]; } - def : Property<"declaration", TemplateDeclRef> { - let Read = [{ qtn->getTemplateDecl() }]; + def : Property<"underlyingTemplateName", TemplateName> { + let Read = [{ qtn->getUnderlyingTemplate() }]; } def : Creator<[{ return ctx.getQualifiedTemplateName(qualifier, hasTemplateKeyword, - declaration); + underlyingTemplateName); }]>; } let Class = PropertyTypeCase<TemplateName, "DependentTemplate"> in { @@ -687,28 +713,40 @@ let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParm"> in { def : ReadHelper<[{ auto parm = node.getAsSubstTemplateTemplateParm(); }]>; - def : Property<"parameter", TemplateTemplateParmDeclRef> { - let Read = [{ parm->getParameter() }]; - } def : Property<"replacement", TemplateName> { let Read = [{ parm->getReplacement() }]; } + def : Property<"associatedDecl", DeclRef> { + let Read = [{ parm->getAssociatedDecl() }]; + } + def : Property<"index", UInt32> { + let Read = [{ parm->getIndex() }]; + } + def : Property<"packIndex", Optional<UInt32>> { + let Read = [{ parm->getPackIndex() }]; + } def : Creator<[{ - return ctx.getSubstTemplateTemplateParm(parameter, replacement); + return ctx.getSubstTemplateTemplateParm(replacement, associatedDecl, index, packIndex); }]>; } let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in { def : ReadHelper<[{ auto parm = node.getAsSubstTemplateTemplateParmPack(); }]>; - def : Property<"parameterPack", TemplateTemplateParmDeclRef> { - let Read = [{ parm->getParameterPack() }]; - } def : Property<"argumentPack", TemplateArgument> { let Read = [{ parm->getArgumentPack() }]; } + def : Property<"associatedDecl", DeclRef> { + let Read = [{ parm->getAssociatedDecl() }]; + } + def : Property<"index", UInt32> { + let Read = [{ parm->getIndex() }]; + } + def : Property<"final", Bool> { + let Read = [{ parm->getFinal() }]; + } def : Creator<[{ - return ctx.getSubstTemplateTemplateParmPack(parameterPack, argumentPack); + return ctx.getSubstTemplateTemplateParmPack(argumentPack, associatedDecl, index, final); }]>; } @@ -724,8 +762,11 @@ let Class = PropertyTypeCase<TemplateArgument, "Type"> in { def : Property<"type", QualType> { let Read = [{ node.getAsType() }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ - return TemplateArgument(type); + return TemplateArgument(type, /* isNullPtr */ false, isDefaulted); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Declaration"> in { @@ -735,16 +776,22 @@ let Class = PropertyTypeCase<TemplateArgument, "Declaration"> in { def : Property<"parameterType", QualType> { let Read = [{ node.getParamTypeForDecl() }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ - return TemplateArgument(declaration, parameterType); + return TemplateArgument(declaration, parameterType, isDefaulted); }]>; } let Class = PropertyTypeCase<TemplateArgument, "NullPtr"> in { def : Property<"type", QualType> { let Read = [{ node.getNullPtrType() }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ - return TemplateArgument(type, /*nullptr*/ true); + return TemplateArgument(type, /*nullptr*/ true, isDefaulted); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Integral"> in { @@ -754,16 +801,36 @@ let Class = PropertyTypeCase<TemplateArgument, "Integral"> in { def : Property<"type", QualType> { let Read = [{ node.getIntegralType() }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } + def : Creator<[{ + return TemplateArgument(ctx, value, type, isDefaulted); + }]>; +} +let Class = PropertyTypeCase<TemplateArgument, "StructuralValue"> in { + def : Property<"value", APValue> { + let Read = [{ node.getAsStructuralValue() }]; + } + def : Property<"type", QualType> { + let Read = [{ node.getStructuralValueType() }]; + } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ - return TemplateArgument(ctx, value, type); + return TemplateArgument(ctx, type, value, isDefaulted); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Template"> in { def : Property<"name", TemplateName> { let Read = [{ node.getAsTemplateOrTemplatePattern() }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ - return TemplateArgument(name); + return TemplateArgument(name, isDefaulted); }]>; } let Class = PropertyTypeCase<TemplateArgument, "TemplateExpansion"> in { @@ -773,22 +840,29 @@ let Class = PropertyTypeCase<TemplateArgument, "TemplateExpansion"> in { def : Property<"numExpansions", Optional<UInt32>> { let Read = [{ // Translate unsigned -> uint32_t just in case. - node.getNumTemplateExpansions().map( - [](unsigned i) { return uint32_t(i); }) + llvm::transformOptional(node.getNumTemplateExpansions(), + [](unsigned i) { return uint32_t(i); }) }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ - auto numExpansionsUnsigned = - numExpansions.map([](uint32_t i) { return unsigned(i); }); - return TemplateArgument(name, numExpansionsUnsigned); + auto numExpansionsUnsigned = llvm::transformOptional( + numExpansions, [](uint32_t i) { return unsigned(i); }); + + return TemplateArgument(name, numExpansionsUnsigned, isDefaulted); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Expression"> in { def : Property<"expression", ExprRef> { let Read = [{ node.getAsExpr() }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ - return TemplateArgument(expression); + return TemplateArgument(expression, isDefaulted); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Pack"> in { @@ -800,6 +874,6 @@ let Class = PropertyTypeCase<TemplateArgument, "Pack"> in { TemplateArgument *ctxElements = new (ctx) TemplateArgument[elements.size()]; for (size_t i = 0, e = elements.size(); i != e; ++i) ctxElements[i] = elements[i]; - return TemplateArgument(llvm::makeArrayRef(ctxElements, elements.size())); + return TemplateArgument(llvm::ArrayRef(ctxElements, elements.size())); }]>; } diff --git a/contrib/llvm-project/clang/include/clang/AST/QualTypeNames.h b/contrib/llvm-project/clang/include/clang/AST/QualTypeNames.h index 8313e0441be5..daa86cda2d99 100644 --- a/contrib/llvm-project/clang/include/clang/AST/QualTypeNames.h +++ b/contrib/llvm-project/clang/include/clang/AST/QualTypeNames.h @@ -89,4 +89,4 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, bool WithGlobalNsPrefix = false); } // end namespace TypeName } // end namespace clang -#endif // LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H +#endif // LLVM_CLANG_AST_QUALTYPENAMES_H diff --git a/contrib/llvm-project/clang/include/clang/AST/Randstruct.h b/contrib/llvm-project/clang/include/clang/AST/Randstruct.h new file mode 100644 index 000000000000..d5eaf30919e3 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/AST/Randstruct.h @@ -0,0 +1,35 @@ +//===- Randstruct.h - Interfact for structure randomization -------*- 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 contains the interface for Clang's structure field layout +// randomization. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_RANDSTRUCT_H +#define LLVM_CLANG_AST_RANDSTRUCT_H + +namespace llvm { +template <typename T> class SmallVectorImpl; +} // end namespace llvm + +namespace clang { + +class ASTContext; +class Decl; +class RecordDecl; + +namespace randstruct { + +bool randomizeStructureLayout(const ASTContext &Context, RecordDecl *RD, + llvm::SmallVectorImpl<Decl *> &FinalOrdering); + +} // namespace randstruct +} // namespace clang + +#endif // LLVM_CLANG_AST_RANDSTRUCT_H diff --git a/contrib/llvm-project/clang/include/clang/AST/RawCommentList.h b/contrib/llvm-project/clang/include/clang/AST/RawCommentList.h index a18432c2b768..53aae24fa7bb 100644 --- a/contrib/llvm-project/clang/include/clang/AST/RawCommentList.h +++ b/contrib/llvm-project/clang/include/clang/AST/RawCommentList.h @@ -115,6 +115,17 @@ public: return extractBriefText(Context); } + bool hasUnsupportedSplice(const SourceManager &SourceMgr) const { + if (!isInvalid()) + return false; + StringRef Text = getRawText(SourceMgr); + if (Text.size() < 6 || Text[0] != '/') + return false; + if (Text[1] == '*') + return Text[Text.size() - 1] != '/' || Text[Text.size() - 2] != '*'; + return Text[1] != '/'; + } + /// Returns sanitized comment text, suitable for presentation in editor UIs. /// E.g. will transform: /// // This is a long multiline comment. @@ -139,6 +150,21 @@ public: std::string getFormattedText(const SourceManager &SourceMgr, DiagnosticsEngine &Diags) const; + struct CommentLine { + std::string Text; + PresumedLoc Begin; + PresumedLoc End; + + CommentLine(StringRef Text, PresumedLoc Begin, PresumedLoc End) + : Text(Text), Begin(Begin), End(End) {} + }; + + /// Returns sanitized comment text as separated lines with locations in + /// source, suitable for further processing and rendering requiring source + /// locations. + std::vector<CommentLine> getFormattedLines(const SourceManager &SourceMgr, + DiagnosticsEngine &Diags) const; + /// Parse the comment, assuming it is attached to decl \c D. comments::FullComment *parse(const ASTContext &Context, const Preprocessor *PP, const Decl *D) const; @@ -147,11 +173,12 @@ private: SourceRange Range; mutable StringRef RawText; - mutable const char *BriefText; + mutable const char *BriefText = nullptr; mutable bool RawTextValid : 1; ///< True if RawText is valid mutable bool BriefTextValid : 1; ///< True if BriefText is valid + LLVM_PREFERRED_TYPE(CommentKind) unsigned Kind : 3; /// True if comment is attached to a declaration in ASTContext. diff --git a/contrib/llvm-project/clang/include/clang/AST/RecursiveASTVisitor.h b/contrib/llvm-project/clang/include/clang/AST/RecursiveASTVisitor.h index 9bfa5b9c2326..2aee6a947141 100644 --- a/contrib/llvm-project/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/contrib/llvm-project/clang/include/clang/AST/RecursiveASTVisitor.h @@ -13,18 +13,19 @@ #ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H #define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H +#include "clang/AST/ASTConcept.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclarationName.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" #include "clang/AST/LambdaCapture.h" @@ -68,30 +69,17 @@ template <typename T, typename U, typename R, typename... P> struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)> : std::true_type {}; -template <bool has_same_type> struct is_same_method_impl { - template <typename FirstMethodPtrTy, typename SecondMethodPtrTy> - static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr, - SecondMethodPtrTy SecondMethodPtr) { - return false; - } -}; - -template <> struct is_same_method_impl<true> { - template <typename FirstMethodPtrTy, typename SecondMethodPtrTy> - static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr, - SecondMethodPtrTy SecondMethodPtr) { - return FirstMethodPtr == SecondMethodPtr; - } -}; - /// Returns true if and only if \p FirstMethodPtr and \p SecondMethodPtr /// are pointers to the same non-static member function. template <typename FirstMethodPtrTy, typename SecondMethodPtrTy> -bool isSameMethod(FirstMethodPtrTy FirstMethodPtr, - SecondMethodPtrTy SecondMethodPtr) { - return is_same_method_impl<has_same_member_pointer_type< - FirstMethodPtrTy, - SecondMethodPtrTy>::value>::isSameMethod(FirstMethodPtr, SecondMethodPtr); +LLVM_ATTRIBUTE_ALWAYS_INLINE LLVM_ATTRIBUTE_NODEBUG auto +isSameMethod([[maybe_unused]] FirstMethodPtrTy FirstMethodPtr, + [[maybe_unused]] SecondMethodPtrTy SecondMethodPtr) + -> bool { + if constexpr (has_same_member_pointer_type<FirstMethodPtrTy, + SecondMethodPtrTy>::value) + return FirstMethodPtr == SecondMethodPtr; + return false; } } // end namespace detail @@ -288,8 +276,7 @@ public: /// /// \returns false if the visitation was terminated early, true otherwise. // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead. - bool TraverseTemplateArguments(const TemplateArgument *Args, - unsigned NumArgs); + bool TraverseTemplateArguments(ArrayRef<TemplateArgument> Args); /// Recursively visit a base specifier. This can be overridden by a /// subclass. @@ -319,11 +306,19 @@ public: bool TraverseSynOrSemInitListExpr(InitListExpr *S, DataRecursionQueue *Queue = nullptr); - /// Recursively visit a reference to a concept with potential arguments. + /// Recursively visit an Objective-C protocol reference with location + /// information. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc); + + /// Recursively visit concept reference with location information. /// /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseConceptReference(const ConceptReference &C); + bool TraverseConceptReference(ConceptReference *CR); + // Visit concept reference. + bool VisitConceptReference(ConceptReference *CR) { return true; } // ---- Methods on Attrs ---- // Visit an attribute. @@ -469,6 +464,13 @@ public: DEF_TRAVERSE_TMPL_INST(Function) #undef DEF_TRAVERSE_TMPL_INST + bool TraverseTypeConstraint(const TypeConstraint *C); + + bool TraverseConceptRequirement(concepts::Requirement *R); + bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R); + bool TraverseConceptExprRequirement(concepts::ExprRequirement *R); + bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R); + bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue); private: @@ -506,6 +508,43 @@ private: }; template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseTypeConstraint( + const TypeConstraint *C) { + if (!getDerived().shouldVisitImplicitCode()) { + TRY_TO(TraverseConceptReference(C->getConceptReference())); + return true; + } + if (Expr *IDC = C->getImmediatelyDeclaredConstraint()) { + TRY_TO(TraverseStmt(IDC)); + } else { + // Avoid traversing the ConceptReference in the TypeConstraint + // if we have an immediately-declared-constraint, otherwise + // we'll end up visiting the concept and the arguments in + // the TC twice. + TRY_TO(TraverseConceptReference(C->getConceptReference())); + } + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseConceptRequirement( + concepts::Requirement *R) { + switch (R->getKind()) { + case concepts::Requirement::RK_Type: + return getDerived().TraverseConceptTypeRequirement( + cast<concepts::TypeRequirement>(R)); + case concepts::Requirement::RK_Simple: + case concepts::Requirement::RK_Compound: + return getDerived().TraverseConceptExprRequirement( + cast<concepts::ExprRequirement>(R)); + case concepts::Requirement::RK_Nested: + return getDerived().TraverseConceptNestedRequirement( + cast<concepts::NestedRequirement>(R)); + } + llvm_unreachable("unexpected case"); +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) { // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. @@ -525,6 +564,40 @@ bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, #undef DISPATCH_STMT template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseConceptTypeRequirement( + concepts::TypeRequirement *R) { + if (R->isSubstitutionFailure()) + return true; + return getDerived().TraverseTypeLoc(R->getType()->getTypeLoc()); +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseConceptExprRequirement( + concepts::ExprRequirement *R) { + if (!R->isExprSubstitutionFailure()) + TRY_TO(TraverseStmt(R->getExpr())); + auto &RetReq = R->getReturnTypeRequirement(); + if (RetReq.isTypeConstraint()) { + if (getDerived().shouldVisitImplicitCode()) { + TRY_TO(TraverseTemplateParameterListHelper( + RetReq.getTypeConstraintTemplateParameterList())); + } else { + // Template parameter list is implicit, visit constraint directly. + TRY_TO(TraverseTypeConstraint(RetReq.getTypeConstraint())); + } + } + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseConceptNestedRequirement( + concepts::NestedRequirement *R) { + if (!R->hasInvalidConstraint()) + return getDerived().TraverseStmt(R->getConstraintExpr()); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::PostVisitStmt(Stmt *S) { // In pre-order traversal mode, each Traverse##STMT method is responsible for // calling WalkUpFrom. Therefore, if the user overrides Traverse##STMT and @@ -777,6 +850,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( case TemplateArgument::Declaration: case TemplateArgument::Integral: case TemplateArgument::NullPtr: + case TemplateArgument::StructuralValue: return true; case TemplateArgument::Type: @@ -791,8 +865,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( return getDerived().TraverseStmt(Arg.getAsExpr()); case TemplateArgument::Pack: - return getDerived().TraverseTemplateArguments(Arg.pack_begin(), - Arg.pack_size()); + return getDerived().TraverseTemplateArguments(Arg.pack_elements()); } return true; @@ -810,6 +883,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( case TemplateArgument::Declaration: case TemplateArgument::Integral: case TemplateArgument::NullPtr: + case TemplateArgument::StructuralValue: return true; case TemplateArgument::Type: { @@ -832,8 +906,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( return getDerived().TraverseStmt(ArgLoc.getSourceExpression()); case TemplateArgument::Pack: - return getDerived().TraverseTemplateArguments(Arg.pack_begin(), - Arg.pack_size()); + return getDerived().TraverseTemplateArguments(Arg.pack_elements()); } return true; @@ -841,10 +914,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments( - const TemplateArgument *Args, unsigned NumArgs) { - for (unsigned I = 0; I != NumArgs; ++I) { - TRY_TO(TraverseTemplateArgument(Args[I])); - } + ArrayRef<TemplateArgument> Args) { + for (const TemplateArgument &Arg : Args) + TRY_TO(TraverseTemplateArgument(Arg)); return true; } @@ -981,13 +1053,14 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, { TRY_TO(TraverseStmt(NE)); }) +DEF_TRAVERSE_TYPE(UsingType, {}) DEF_TRAVERSE_TYPE(UnresolvedUsingType, {}) DEF_TRAVERSE_TYPE(TypedefType, {}) DEF_TRAVERSE_TYPE(TypeOfExprType, { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) -DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnderlyingType())); }) +DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnmodifiedType())); }) DEF_TRAVERSE_TYPE(DecltypeType, { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) @@ -1000,8 +1073,7 @@ DEF_TRAVERSE_TYPE(UnaryTransformType, { DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType())); if (T->isConstrained()) { - TRY_TO(TraverseDecl(T->getTypeConstraintConcept())); - TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); + TRY_TO(TraverseTemplateArguments(T->getTypeConstraintArguments())); } }) DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, { @@ -1021,7 +1093,7 @@ DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, { DEF_TRAVERSE_TYPE(TemplateSpecializationType, { TRY_TO(TraverseTemplateName(T->getTemplateName())); - TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); + TRY_TO(TraverseTemplateArguments(T->template_arguments())); }) DEF_TRAVERSE_TYPE(InjectedClassNameType, {}) @@ -1029,6 +1101,9 @@ DEF_TRAVERSE_TYPE(InjectedClassNameType, {}) DEF_TRAVERSE_TYPE(AttributedType, { TRY_TO(TraverseType(T->getModifiedType())); }) +DEF_TRAVERSE_TYPE(BTFTagAttributedType, + { TRY_TO(TraverseType(T->getWrappedType())); }) + DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); }) DEF_TRAVERSE_TYPE(MacroQualifiedType, @@ -1046,7 +1121,7 @@ DEF_TRAVERSE_TYPE(DependentNameType, DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); - TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); + TRY_TO(TraverseTemplateArguments(T->template_arguments())); }) DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); }) @@ -1072,8 +1147,8 @@ DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); }) DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); }) -DEF_TRAVERSE_TYPE(ExtIntType, {}) -DEF_TRAVERSE_TYPE(DependentExtIntType, +DEF_TRAVERSE_TYPE(BitIntType, {}) +DEF_TRAVERSE_TYPE(DependentBitIntType, { TRY_TO(TraverseStmt(T->getNumBitsExpr())); }) #undef DEF_TRAVERSE_TYPE @@ -1252,6 +1327,7 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, { TRY_TO(TraverseStmt(NE)); }) +DEF_TRAVERSE_TYPELOC(UsingType, {}) DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) DEF_TRAVERSE_TYPELOC(TypedefType, {}) @@ -1259,7 +1335,7 @@ DEF_TRAVERSE_TYPELOC(TypeOfExprType, { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); }) DEF_TRAVERSE_TYPELOC(TypeOfType, { - TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); + TRY_TO(TraverseTypeLoc(TL.getUnmodifiedTInfo()->getTypeLoc())); }) // FIXME: location of underlying expr @@ -1274,10 +1350,7 @@ DEF_TRAVERSE_TYPELOC(UnaryTransformType, { DEF_TRAVERSE_TYPELOC(AutoType, { TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); if (TL.isConstrained()) { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getNestedNameSpecifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(TL.getConceptNameInfo())); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) - TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); + TRY_TO(TraverseConceptReference(TL.getConceptReference())); } }) @@ -1314,6 +1387,9 @@ DEF_TRAVERSE_TYPELOC(MacroQualifiedType, DEF_TRAVERSE_TYPELOC(AttributedType, { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); }) +DEF_TRAVERSE_TYPELOC(BTFTagAttributedType, + { TRY_TO(TraverseTypeLoc(TL.getWrappedLoc())); }) + DEF_TRAVERSE_TYPELOC(ElaboratedType, { if (TL.getQualifierLoc()) { TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); @@ -1338,7 +1414,12 @@ DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { DEF_TRAVERSE_TYPELOC(PackExpansionType, { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); }) -DEF_TRAVERSE_TYPELOC(ObjCTypeParamType, {}) +DEF_TRAVERSE_TYPELOC(ObjCTypeParamType, { + for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) { + ObjCProtocolLoc ProtocolLoc(TL.getProtocol(I), TL.getProtocolLoc(I)); + TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); + } +}) DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {}) @@ -1349,6 +1430,10 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectType, { TRY_TO(TraverseTypeLoc(TL.getBaseLoc())); for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i) TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc())); + for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) { + ObjCProtocolLoc ProtocolLoc(TL.getProtocol(I), TL.getProtocolLoc(I)); + TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); + } }) DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, @@ -1358,8 +1443,8 @@ DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) -DEF_TRAVERSE_TYPELOC(ExtIntType, {}) -DEF_TRAVERSE_TYPELOC(DependentExtIntType, { +DEF_TRAVERSE_TYPELOC(BitIntType, {}) +DEF_TRAVERSE_TYPELOC(DependentBitIntType, { TRY_TO(TraverseStmt(TL.getTypePtr()->getNumBitsExpr())); }) @@ -1440,6 +1525,8 @@ DEF_TRAVERSE_DECL(CapturedDecl, { DEF_TRAVERSE_DECL(EmptyDecl, {}) +DEF_TRAVERSE_DECL(HLSLBufferDecl, {}) + DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, { TRY_TO(TraverseStmt(D->getTemporaryExpr())); }) @@ -1447,14 +1534,21 @@ DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, { DEF_TRAVERSE_DECL(FileScopeAsmDecl, { TRY_TO(TraverseStmt(D->getAsmString())); }) +DEF_TRAVERSE_DECL(TopLevelStmtDecl, { TRY_TO(TraverseStmt(D->getStmt())); }) + DEF_TRAVERSE_DECL(ImportDecl, {}) DEF_TRAVERSE_DECL(FriendDecl, { // Friend is either decl or a type. - if (D->getFriendType()) + if (D->getFriendType()) { TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); - else + // Traverse any CXXRecordDecl owned by this type, since + // it will not be in the parent context: + if (auto *ET = D->getFriendType()->getType()->getAs<ElaboratedType>()) + TRY_TO(TraverseDecl(ET->getOwnedTagDecl())); + } else { TRY_TO(TraverseDecl(D->getFriendDecl())); + } }) DEF_TRAVERSE_DECL(FriendTemplateDecl, { @@ -1471,16 +1565,6 @@ DEF_TRAVERSE_DECL(FriendTemplateDecl, { } }) -DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, { - TRY_TO(TraverseDecl(D->getSpecialization())); - - if (D->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper( - D->getTemplateArgsAsWritten()->getTemplateArgs(), - D->getTemplateArgsAsWritten()->NumTemplateArgs)); - } -}) - DEF_TRAVERSE_DECL(LinkageSpecDecl, {}) DEF_TRAVERSE_DECL(ExportDecl, {}) @@ -1539,12 +1623,16 @@ DEF_TRAVERSE_DECL( DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement }) -DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement +DEF_TRAVERSE_DECL(ObjCCategoryDecl, { if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) { for (auto typeParam : *typeParamList) { TRY_TO(TraverseObjCTypeParamDecl(typeParam)); } } + for (auto It : llvm::zip(D->protocols(), D->protocol_locs())) { + ObjCProtocolLoc ProtocolLoc(std::get<0>(It), std::get<1>(It)); + TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); + } }) DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement @@ -1553,7 +1641,7 @@ DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement }) -DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement +DEF_TRAVERSE_DECL(ObjCInterfaceDecl, { if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) { for (auto typeParam : *typeParamList) { TRY_TO(TraverseObjCTypeParamDecl(typeParam)); @@ -1563,10 +1651,22 @@ DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) { TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc())); } + if (D->isThisDeclarationADefinition()) { + for (auto It : llvm::zip(D->protocols(), D->protocol_locs())) { + ObjCProtocolLoc ProtocolLoc(std::get<0>(It), std::get<1>(It)); + TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); + } + } }) -DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement - }) +DEF_TRAVERSE_DECL(ObjCProtocolDecl, { + if (D->isThisDeclarationADefinition()) { + for (auto It : llvm::zip(D->protocols(), D->protocol_locs())) { + ObjCProtocolLoc ProtocolLoc(std::get<0>(It), std::get<1>(It)); + TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); + } + } +}) DEF_TRAVERSE_DECL(ObjCMethodDecl, { if (D->getReturnTypeSourceInfo()) { @@ -1603,7 +1703,8 @@ DEF_TRAVERSE_DECL(UsingDecl, { TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); }) -DEF_TRAVERSE_DECL(UsingEnumDecl, {}) +DEF_TRAVERSE_DECL(UsingEnumDecl, + { TRY_TO(TraverseTypeLoc(D->getEnumTypeLoc())); }) DEF_TRAVERSE_DECL(UsingPackDecl, {}) @@ -1681,10 +1782,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( ClassTemplateDecl *D) { for (auto *SD : D->specializations()) { for (auto *RD : SD->redecls()) { - // We don't want to visit injected-class-names in this traversal. - if (cast<CXXRecordDecl>(RD)->isInjectedClassName()) - continue; - + assert(!cast<CXXRecordDecl>(RD)->isInjectedClassName()); switch ( cast<ClassTemplateSpecializationDecl>(RD)->getSpecializationKind()) { // Visit the implicit instantiations with the requested pattern. @@ -1802,17 +1900,8 @@ DEF_TRAVERSE_DECL(BuiltinTemplateDecl, { template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateTypeParamDeclConstraints( const TemplateTypeParmDecl *D) { - if (const auto *TC = D->getTypeConstraint()) { - if (Expr *IDC = TC->getImmediatelyDeclaredConstraint()) { - TRY_TO(TraverseStmt(IDC)); - } else { - // Avoid traversing the ConceptReference in the TypeCosntraint - // if we have an immediately-declared-constraint, otherwise - // we'll end up visiting the concept and the arguments in - // the TC twice. - TRY_TO(TraverseConceptReference(*TC)); - } - } + if (const auto *TC = D->getTypeConstraint()) + TRY_TO(TraverseTypeConstraint(TC)); return true; } @@ -1863,10 +1952,9 @@ DEF_TRAVERSE_DECL(UnresolvedUsingIfExistsDecl, {}) DEF_TRAVERSE_DECL(EnumDecl, { TRY_TO(TraverseDeclTemplateParameterLists(D)); - if (D->getTypeForDecl()) - TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + if (auto *TSI = D->getIntegerTypeSourceInfo()) + TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); // The enumerators are already traversed by // decls_begin()/decls_end(). }) @@ -1907,7 +1995,7 @@ DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); }) DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) -#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND) \ +#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \ /* For implicit instantiations ("set<int> x;"), we don't want to \ recurse at all, since the instatiated template isn't written in \ @@ -1920,18 +2008,23 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \ TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \ \ - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); \ - if (!getDerived().shouldVisitTemplateInstantiations() && \ - D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \ + if (getDerived().shouldVisitTemplateInstantiations() || \ + D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \ + /* Traverse base definition for explicit specializations */ \ + TRY_TO(Traverse##DECLKIND##Helper(D)); \ + } else { \ + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); \ + \ /* Returning from here skips traversing the \ declaration context of the *TemplateSpecializationDecl \ (embedded in the DEF_TRAVERSE_DECL() macro) \ which contains the instantiated members of the template. */ \ return true; \ + } \ }) -DEF_TRAVERSE_TMPL_SPEC_DECL(Class) -DEF_TRAVERSE_TMPL_SPEC_DECL(Var) +DEF_TRAVERSE_TMPL_SPEC_DECL(Class, CXXRecord) +DEF_TRAVERSE_TMPL_SPEC_DECL(Var, Var) template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( @@ -1945,12 +2038,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( #define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \ /* The partial specialization. */ \ - if (TemplateParameterList *TPL = D->getTemplateParameters()) { \ - for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); \ - I != E; ++I) { \ - TRY_TO(TraverseDecl(*I)); \ - } \ - } \ + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ /* The args that remains unspecialized. */ \ TRY_TO(TraverseTemplateArgumentLocsHelper( \ D->getTemplateArgsAsWritten()->getTemplateArgs(), \ @@ -2004,6 +2092,7 @@ DEF_TRAVERSE_DECL(BindingDecl, { DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); }) DEF_TRAVERSE_DECL(MSGuidDecl, {}) +DEF_TRAVERSE_DECL(UnnamedGlobalConstantDecl, {}) DEF_TRAVERSE_DECL(TemplateParamObjectDecl, {}) @@ -2011,7 +2100,7 @@ DEF_TRAVERSE_DECL(FieldDecl, { TRY_TO(TraverseDeclaratorHelper(D)); if (D->isBitField()) TRY_TO(TraverseStmt(D->getBitWidth())); - else if (D->hasInClassInitializer()) + if (D->hasInClassInitializer()) TRY_TO(TraverseStmt(D->getInClassInitializer())); }) @@ -2052,6 +2141,13 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { TALI->NumTemplateArgs)); } } + } else if (const DependentFunctionTemplateSpecializationInfo *DFSI = + D->getDependentSpecializationInfo()) { + if (const ASTTemplateArgumentListInfo *TALI = + DFSI->TemplateArgumentsAsWritten) { + TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(), + TALI->NumTemplateArgs)); + } } // Visit the function type itself, which can be either @@ -2099,7 +2195,13 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { } if (VisitBody) { - TRY_TO(TraverseStmt(D->getBody())); // Function body. + TRY_TO(TraverseStmt(D->getBody())); + // Body may contain using declarations whose shadows are parented to the + // FunctionDecl itself. + for (auto *Child : D->decls()) { + if (isa<UsingShadowDecl>(Child)) + TRY_TO(TraverseDecl(Child)); + } } return true; } @@ -2183,6 +2285,10 @@ DEF_TRAVERSE_DECL(ParmVarDecl, { DEF_TRAVERSE_DECL(RequiresExprBodyDecl, {}) +DEF_TRAVERSE_DECL(ImplicitConceptSpecializationDecl, { + TRY_TO(TraverseTemplateArguments(D->getTemplateArguments())); +}) + #undef DEF_TRAVERSE_DECL // ----------------- Stmt traversal ----------------- @@ -2393,15 +2499,25 @@ bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr( return true; } -template<typename Derived> +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseObjCProtocolLoc( + ObjCProtocolLoc ProtocolLoc) { + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseConceptReference( - const ConceptReference &C) { - TRY_TO(TraverseNestedNameSpecifierLoc(C.getNestedNameSpecifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(C.getConceptNameInfo())); - if (C.hasExplicitTemplateArgs()) + ConceptReference *CR) { + if (!getDerived().shouldTraversePostOrder()) + TRY_TO(VisitConceptReference(CR)); + TRY_TO(TraverseNestedNameSpecifierLoc(CR->getNestedNameSpecifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(CR->getConceptNameInfo())); + if (CR->hasExplicitTemplateArgs()) TRY_TO(TraverseTemplateArgumentLocsHelper( - C.getTemplateArgsAsWritten()->getTemplateArgs(), - C.getTemplateArgsAsWritten()->NumTemplateArgs)); + CR->getTemplateArgsAsWritten()->getTemplateArgs(), + CR->getTemplateArgsAsWritten()->NumTemplateArgs)); + if (getDerived().shouldTraversePostOrder()) + TRY_TO(VisitConceptReference(CR)); return true; } @@ -2436,7 +2552,11 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr( // are interleaved. We also need to watch out for null types (default // generic associations). DEF_TRAVERSE_STMT(GenericSelectionExpr, { - TRY_TO(TraverseStmt(S->getControllingExpr())); + if (S->isExprPredicate()) + TRY_TO(TraverseStmt(S->getControllingExpr())); + else + TRY_TO(TraverseTypeLoc(S->getControllingType()->getTypeLoc())); + for (const GenericSelectionExpr::Association Assoc : S->associations()) { if (TypeSourceInfo *TSI = Assoc.getTypeSourceInfo()) TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); @@ -2606,7 +2726,11 @@ DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { TRY_TO(TraverseStmt(S->getExpr())); }) -DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {}) +DEF_TRAVERSE_STMT(CXXDefaultInitExpr, { + if (getDerived().shouldVisitImplicitCode()) + TRY_TO(TraverseStmt(S->getExpr())); +}) + DEF_TRAVERSE_STMT(CXXDeleteExpr, {}) DEF_TRAVERSE_STMT(ExprWithCleanups, {}) DEF_TRAVERSE_STMT(CXXInheritedCtorInitExpr, {}) @@ -2735,6 +2859,7 @@ DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {}) DEF_TRAVERSE_STMT(FunctionParmPackExpr, {}) DEF_TRAVERSE_STMT(CXXFoldExpr, {}) DEF_TRAVERSE_STMT(AtomicExpr, {}) +DEF_TRAVERSE_STMT(CXXParenListInitExpr, {}) DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { if (S->getLifetimeExtendedTemporaryDecl()) { @@ -2778,7 +2903,7 @@ DEF_TRAVERSE_STMT(CoyieldExpr, { }) DEF_TRAVERSE_STMT(ConceptSpecializationExpr, { - TRY_TO(TraverseConceptReference(*S)); + TRY_TO(TraverseConceptReference(S->getConceptReference())); }) DEF_TRAVERSE_STMT(RequiresExpr, { @@ -2786,21 +2911,7 @@ DEF_TRAVERSE_STMT(RequiresExpr, { for (ParmVarDecl *Parm : S->getLocalParameters()) TRY_TO(TraverseDecl(Parm)); for (concepts::Requirement *Req : S->getRequirements()) - if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Req)) { - if (!TypeReq->isSubstitutionFailure()) - TRY_TO(TraverseTypeLoc(TypeReq->getType()->getTypeLoc())); - } else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Req)) { - if (!ExprReq->isExprSubstitutionFailure()) - TRY_TO(TraverseStmt(ExprReq->getExpr())); - auto &RetReq = ExprReq->getReturnTypeRequirement(); - if (RetReq.isTypeConstraint()) - TRY_TO(TraverseTemplateParameterListHelper( - RetReq.getTypeConstraintTemplateParameterList())); - } else { - auto *NestedReq = cast<concepts::NestedRequirement>(Req); - if (!NestedReq->isSubstitutionFailure()) - TRY_TO(TraverseStmt(NestedReq->getConstraintExpr())); - } + TRY_TO(TraverseConceptRequirement(Req)); }) // These literals (all of them) do not need any action. @@ -2842,6 +2953,9 @@ RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) { return TraverseOMPExecutableDirective(S); } +DEF_TRAVERSE_STMT(OMPMetaDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPParallelDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2866,6 +2980,9 @@ DEF_TRAVERSE_STMT(OMPSectionsDirective, DEF_TRAVERSE_STMT(OMPSectionDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPScopeDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPSingleDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2886,6 +3003,9 @@ DEF_TRAVERSE_STMT(OMPParallelForSimdDirective, DEF_TRAVERSE_STMT(OMPParallelMasterDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPParallelMaskedDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2967,6 +3087,18 @@ DEF_TRAVERSE_STMT(OMPParallelMasterTaskLoopDirective, DEF_TRAVERSE_STMT(OMPParallelMasterTaskLoopSimdDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPMaskedTaskLoopDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPMaskedTaskLoopSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPParallelMaskedTaskLoopDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPParallelMaskedTaskLoopSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPDistributeDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -3021,6 +3153,24 @@ DEF_TRAVERSE_STMT(OMPDispatchDirective, DEF_TRAVERSE_STMT(OMPMaskedDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPGenericLoopDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTeamsGenericLoopDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTargetTeamsGenericLoopDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPParallelGenericLoopDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTargetParallelGenericLoopDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPErrorDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { @@ -3092,6 +3242,12 @@ RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPAlignClause(OMPAlignClause *C) { + TRY_TO(TraverseStmt(C->getAlignment())); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) { TRY_TO(TraverseStmt(C->getSafelen())); return true; @@ -3169,6 +3325,22 @@ bool RecursiveASTVisitor<Derived>::VisitOMPAtomicDefaultMemOrderClause( } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPAtClause(OMPAtClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSeverityClause(OMPSeverityClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPMessageClause(OMPMessageClause *C) { + TRY_TO(TraverseStmt(C->getMessageString())); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) { TRY_TO(VisitOMPClauseWithPreInit(C)); @@ -3219,6 +3391,16 @@ bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPCompareClause(OMPCompareClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPFailClause(OMPFailClause *) { + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) { return true; } @@ -3627,6 +3809,13 @@ bool RecursiveASTVisitor<Derived>::VisitOMPIsDevicePtrClause( } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPHasDeviceAddrClause( + OMPHasDeviceAddrClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPNontemporalClause( OMPNontemporalClause *C) { TRY_TO(VisitOMPClauseList(C)); @@ -3674,6 +3863,37 @@ bool RecursiveASTVisitor<Derived>::VisitOMPFilterClause(OMPFilterClause *C) { return true; } +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPBindClause(OMPBindClause *C) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPXDynCGroupMemClause( + OMPXDynCGroupMemClause *C) { + TRY_TO(VisitOMPClauseWithPreInit(C)); + TRY_TO(TraverseStmt(C->getSize())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPDoacrossClause( + OMPDoacrossClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPXAttributeClause( + OMPXAttributeClause *C) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPXBareClause(OMPXBareClause *C) { + return true; +} + // FIXME: look at the following tricky-seeming exprs to see if we // need to recurse on anything. These are ones that have methods // returning decls or qualtypes or nestednamespecifier -- though I'm diff --git a/contrib/llvm-project/clang/include/clang/AST/Redeclarable.h b/contrib/llvm-project/clang/include/clang/AST/Redeclarable.h index 77b827c52bfb..091bb886f2d4 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Redeclarable.h +++ b/contrib/llvm-project/clang/include/clang/AST/Redeclarable.h @@ -240,7 +240,7 @@ public: class redecl_iterator { /// Current - The current declaration. decl_type *Current = nullptr; - decl_type *Starter; + decl_type *Starter = nullptr; bool PassedFirst = false; public: @@ -258,7 +258,8 @@ public: redecl_iterator& operator++() { assert(Current && "Advancing while iterator has reached end"); - // Sanity check to avoid infinite loop on invalid redecl chain. + // Make sure we don't infinitely loop on an invalid redecl chain. This + // should never happen. if (Current->isFirstDecl()) { if (PassedFirst) { assert(0 && "Passed first decl twice, invalid redecl chain!"); diff --git a/contrib/llvm-project/clang/include/clang/AST/Stmt.h b/contrib/llvm-project/clang/include/clang/AST/Stmt.h index 8e1d7df97096..55eca4007d17 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Stmt.h +++ b/contrib/llvm-project/clang/include/clang/AST/Stmt.h @@ -13,13 +13,21 @@ #ifndef LLVM_CLANG_AST_STMT_H #define LLVM_CLANG_AST_STMT_H +#include "clang/AST/APValue.h" #include "clang/AST/DeclGroup.h" #include "clang/AST/DependenceFlags.h" +#include "clang/AST/OperationKinds.h" #include "clang/AST/StmtIterator.h" #include "clang/Basic/CapturedStmt.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/Lambda.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/OperatorKinds.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "clang/Basic/TypeTraits.h" +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/PointerIntPair.h" @@ -33,6 +41,7 @@ #include <cassert> #include <cstddef> #include <iterator> +#include <optional> #include <string> namespace llvm { @@ -58,6 +67,13 @@ class SourceManager; class StringLiteral; class Token; class VarDecl; +enum class CharacterLiteralKind; +enum class ConstantResultStorageKind; +enum class CXXConstructionKind; +enum class CXXNewInitializationStyle; +enum class PredefinedIdentKind; +enum class SourceLocIdentKind; +enum class StringLiteralKind; //===----------------------------------------------------------------------===// // AST classes for statements. @@ -99,6 +115,7 @@ protected: friend class Stmt; /// The statement class. + LLVM_PREFERRED_TYPE(StmtClass) unsigned sClass : 8; }; enum { NumStmtBits = 8 }; @@ -108,6 +125,7 @@ protected: friend class ASTStmtWriter; friend class NullStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; /// True if the null statement was preceded by an empty macro, e.g: @@ -115,6 +133,7 @@ protected: /// #define CALL(x) /// CALL(0); /// @endcode + LLVM_PREFERRED_TYPE(bool) unsigned HasLeadingEmptyMacro : 1; /// The location of the semi-colon. @@ -125,17 +144,21 @@ protected: friend class ASTStmtReader; friend class CompoundStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; - unsigned NumStmts : 32 - NumStmtBits; + /// True if the compound statement has one or more pragmas that set some + /// floating-point features. + LLVM_PREFERRED_TYPE(bool) + unsigned HasFPFeatures : 1; - /// The location of the opening "{". - SourceLocation LBraceLoc; + unsigned NumStmts; }; class LabelStmtBitfields { friend class LabelStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; SourceLocation IdentLoc; @@ -145,6 +168,7 @@ protected: friend class ASTStmtReader; friend class AttributedStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; /// Number of attributes. @@ -158,18 +182,23 @@ protected: friend class ASTStmtReader; friend class IfStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; - /// True if this if statement is a constexpr if. - unsigned IsConstexpr : 1; + /// Whether this is a constexpr if, or a consteval if, or neither. + LLVM_PREFERRED_TYPE(IfStatementKind) + unsigned Kind : 3; /// True if this if statement has storage for an else statement. + LLVM_PREFERRED_TYPE(bool) unsigned HasElse : 1; /// True if this if statement has storage for a variable declaration. + LLVM_PREFERRED_TYPE(bool) unsigned HasVar : 1; /// True if this if statement has storage for an init statement. + LLVM_PREFERRED_TYPE(bool) unsigned HasInit : 1; /// The location of the "if". @@ -179,17 +208,21 @@ protected: class SwitchStmtBitfields { friend class SwitchStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; /// True if the SwitchStmt has storage for an init statement. + LLVM_PREFERRED_TYPE(bool) unsigned HasInit : 1; /// True if the SwitchStmt has storage for a condition variable. + LLVM_PREFERRED_TYPE(bool) unsigned HasVar : 1; /// If the SwitchStmt is a switch on an enum value, records whether all /// the enum values were covered by CaseStmts. The coverage information /// value is meant to be a hint for possible clients. + LLVM_PREFERRED_TYPE(bool) unsigned AllEnumCasesCovered : 1; /// The location of the "switch". @@ -200,9 +233,11 @@ protected: friend class ASTStmtReader; friend class WhileStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; /// True if the WhileStmt has storage for a condition variable. + LLVM_PREFERRED_TYPE(bool) unsigned HasVar : 1; /// The location of the "while". @@ -212,6 +247,7 @@ protected: class DoStmtBitfields { friend class DoStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; /// The location of the "do". @@ -221,6 +257,7 @@ protected: class ForStmtBitfields { friend class ForStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; /// The location of the "for". @@ -231,6 +268,7 @@ protected: friend class GotoStmt; friend class IndirectGotoStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; /// The location of the "goto". @@ -240,6 +278,7 @@ protected: class ContinueStmtBitfields { friend class ContinueStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; /// The location of the "continue". @@ -249,6 +288,7 @@ protected: class BreakStmtBitfields { friend class BreakStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; /// The location of the "break". @@ -258,9 +298,11 @@ protected: class ReturnStmtBitfields { friend class ReturnStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; /// True if this ReturnStmt has storage for an NRVO candidate. + LLVM_PREFERRED_TYPE(bool) unsigned HasNRVOCandidate : 1; /// The location of the "return". @@ -271,10 +313,12 @@ protected: friend class SwitchCase; friend class CaseStmt; + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; /// Used by CaseStmt to store whether it is a case statement /// of the form case LHS ... RHS (a GNU extension). + LLVM_PREFERRED_TYPE(bool) unsigned CaseStmtIsGNURange : 1; /// The location of the "case" or "default" keyword. @@ -307,11 +351,15 @@ protected: friend class PseudoObjectExpr; // ctor friend class ShuffleVectorExpr; // ctor + LLVM_PREFERRED_TYPE(StmtBitfields) unsigned : NumStmtBits; + LLVM_PREFERRED_TYPE(ExprValueKind) unsigned ValueKind : 2; + LLVM_PREFERRED_TYPE(ExprObjectKind) unsigned ObjectKind : 3; - unsigned /*ExprDependence*/ Dependent : llvm::BitWidth<ExprDependence>; + LLVM_PREFERRED_TYPE(ExprDependence) + unsigned Dependent : llvm::BitWidth<ExprDependence>; }; enum { NumExprBits = NumStmtBits + 5 + llvm::BitWidth<ExprDependence> }; @@ -320,28 +368,35 @@ protected: friend class ASTStmtWriter; friend class ConstantExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// The kind of result that is tail-allocated. + LLVM_PREFERRED_TYPE(ConstantResultStorageKind) unsigned ResultKind : 2; - /// The kind of Result as defined by APValue::Kind. + /// The kind of Result as defined by APValue::ValueKind. + LLVM_PREFERRED_TYPE(APValue::ValueKind) unsigned APValueKind : 4; - /// When ResultKind == RSK_Int64, true if the tail-allocated integer is - /// unsigned. + /// When ResultKind == ConstantResultStorageKind::Int64, true if the + /// tail-allocated integer is unsigned. + LLVM_PREFERRED_TYPE(bool) unsigned IsUnsigned : 1; - /// When ResultKind == RSK_Int64. the BitWidth of the tail-allocated - /// integer. 7 bits because it is the minimal number of bits to represent a - /// value from 0 to 64 (the size of the tail-allocated integer). + /// When ResultKind == ConstantResultStorageKind::Int64. the BitWidth of the + /// tail-allocated integer. 7 bits because it is the minimal number of bits + /// to represent a value from 0 to 64 (the size of the tail-allocated + /// integer). unsigned BitWidth : 7; - /// When ResultKind == RSK_APValue, true if the ASTContext will cleanup the - /// tail-allocated APValue. + /// When ResultKind == ConstantResultStorageKind::APValue, true if the + /// ASTContext will cleanup the tail-allocated APValue. + LLVM_PREFERRED_TYPE(bool) unsigned HasCleanup : 1; /// True if this ConstantExpr was created for immediate invocation. + LLVM_PREFERRED_TYPE(bool) unsigned IsImmediateInvocation : 1; }; @@ -349,16 +404,22 @@ protected: friend class ASTStmtReader; friend class PredefinedExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; - /// The kind of this PredefinedExpr. One of the enumeration values - /// in PredefinedExpr::IdentKind. + LLVM_PREFERRED_TYPE(PredefinedIdentKind) unsigned Kind : 4; /// True if this PredefinedExpr has a trailing "StringLiteral *" /// for the predefined identifier. + LLVM_PREFERRED_TYPE(bool) unsigned HasFunctionName : 1; + /// True if this PredefinedExpr should be treated as a StringLiteral (for + /// MSVC compatibility). + LLVM_PREFERRED_TYPE(bool) + unsigned IsTransparent : 1; + /// The location of this PredefinedExpr. SourceLocation Loc; }; @@ -367,14 +428,25 @@ protected: friend class ASTStmtReader; // deserialization friend class DeclRefExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; + LLVM_PREFERRED_TYPE(bool) unsigned HasQualifier : 1; + LLVM_PREFERRED_TYPE(bool) unsigned HasTemplateKWAndArgsInfo : 1; + LLVM_PREFERRED_TYPE(bool) unsigned HasFoundDecl : 1; + LLVM_PREFERRED_TYPE(bool) unsigned HadMultipleCandidates : 1; + LLVM_PREFERRED_TYPE(bool) unsigned RefersToEnclosingVariableOrCapture : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned CapturedByCopyInLambdaWithExplicitObjectParameter : 1; + LLVM_PREFERRED_TYPE(NonOdrUseReason) unsigned NonOdrUseReason : 2; + LLVM_PREFERRED_TYPE(bool) + unsigned IsImmediateEscalating : 1; /// The location of the declaration name itself. SourceLocation Loc; @@ -384,9 +456,15 @@ protected: class FloatingLiteralBitfields { friend class FloatingLiteral; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; - unsigned Semantics : 3; // Provides semantics for APFloat construction + static_assert( + llvm::APFloat::S_MaxSemantics < 16, + "Too many Semantics enum values to fit in bitfield of size 4"); + LLVM_PREFERRED_TYPE(llvm::APFloat::Semantics) + unsigned Semantics : 4; // Provides semantics for APFloat construction + LLVM_PREFERRED_TYPE(bool) unsigned IsExact : 1; }; @@ -394,10 +472,12 @@ protected: friend class ASTStmtReader; friend class StringLiteral; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// The kind of this string literal. /// One of the enumeration values of StringLiteral::StringKind. + LLVM_PREFERRED_TYPE(StringLiteralKind) unsigned Kind : 3; /// The width of a single character in bytes. Only values of 1, 2, @@ -405,6 +485,7 @@ protected: /// the target + string kind to the appropriate CharByteWidth. unsigned CharByteWidth : 3; + LLVM_PREFERRED_TYPE(bool) unsigned IsPascal : 1; /// The number of concatenated token this string is made of. @@ -415,22 +496,28 @@ protected: class CharacterLiteralBitfields { friend class CharacterLiteral; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; + LLVM_PREFERRED_TYPE(CharacterLiteralKind) unsigned Kind : 3; }; class UnaryOperatorBitfields { friend class UnaryOperator; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; + LLVM_PREFERRED_TYPE(UnaryOperatorKind) unsigned Opc : 5; + LLVM_PREFERRED_TYPE(bool) unsigned CanOverflow : 1; // /// This is only meaningful for operations on floating point /// types when additional values need to be in trailing storage. /// It is 0 otherwise. + LLVM_PREFERRED_TYPE(bool) unsigned HasFPFeatures : 1; SourceLocation Loc; @@ -439,9 +526,12 @@ protected: class UnaryExprOrTypeTraitExprBitfields { friend class UnaryExprOrTypeTraitExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; + LLVM_PREFERRED_TYPE(UnaryExprOrTypeTrait) unsigned Kind : 3; + LLVM_PREFERRED_TYPE(bool) unsigned IsType : 1; // true if operand is a type, false if an expression. }; @@ -449,6 +539,7 @@ protected: friend class ArraySubscriptExpr; friend class MatrixSubscriptExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; SourceLocation RBracketLoc; @@ -457,14 +548,17 @@ protected: class CallExprBitfields { friend class CallExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; unsigned NumPreArgs : 1; /// True if the callee of the call expression was found using ADL. + LLVM_PREFERRED_TYPE(bool) unsigned UsesADL : 1; /// True if the call expression has some floating-point features. + LLVM_PREFERRED_TYPE(bool) unsigned HasFPFeatures : 1; /// Padding used to align OffsetToTrailingObjects to a byte multiple. @@ -481,15 +575,18 @@ protected: friend class ASTStmtReader; friend class MemberExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// IsArrow - True if this is "X->F", false if this is "X.F". + LLVM_PREFERRED_TYPE(bool) unsigned IsArrow : 1; /// True if this member expression used a nested-name-specifier to /// refer to the member, e.g., "x->Base::f", or found its member via /// a using declaration. When true, a MemberExprNameQualifier /// structure is allocated immediately after the MemberExpr. + LLVM_PREFERRED_TYPE(bool) unsigned HasQualifierOrFoundDecl : 1; /// True if this member expression specified a template keyword @@ -497,15 +594,18 @@ protected: /// x->template f, x->template f<int>. /// When true, an ASTTemplateKWAndArgsInfo structure and its /// TemplateArguments (if any) are present. + LLVM_PREFERRED_TYPE(bool) unsigned HasTemplateKWAndArgsInfo : 1; /// True if this member expression refers to a method that /// was resolved from an overloaded set having size greater than 1. + LLVM_PREFERRED_TYPE(bool) unsigned HadMultipleCandidates : 1; /// Value of type NonOdrUseReason indicating why this MemberExpr does /// not constitute an odr-use of the named declaration. Meaningful only /// when naming a static member. + LLVM_PREFERRED_TYPE(NonOdrUseReason) unsigned NonOdrUseReason : 2; /// This is the location of the -> or . in the expression. @@ -516,12 +616,16 @@ protected: friend class CastExpr; friend class ImplicitCastExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; + LLVM_PREFERRED_TYPE(CastKind) unsigned Kind : 7; + LLVM_PREFERRED_TYPE(bool) unsigned PartOfExplicitCast : 1; // Only set for ImplicitCastExpr. /// True if the call expression has some floating-point features. + LLVM_PREFERRED_TYPE(bool) unsigned HasFPFeatures : 1; /// The number of CXXBaseSpecifiers in the cast. 14 bits would be enough @@ -532,13 +636,16 @@ protected: class BinaryOperatorBitfields { friend class BinaryOperator; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; + LLVM_PREFERRED_TYPE(BinaryOperatorKind) unsigned Opc : 6; /// This is only meaningful for operations on floating point /// types when additional values need to be in trailing storage. /// It is 0 otherwise. + LLVM_PREFERRED_TYPE(bool) unsigned HasFPFeatures : 1; SourceLocation OpLoc; @@ -547,10 +654,12 @@ protected: class InitListExprBitfields { friend class InitListExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// Whether this initializer list originally had a GNU array-range /// designator in it. This is a temporary marker used by CodeGen. + LLVM_PREFERRED_TYPE(bool) unsigned HadArrayRangeDesignator : 1; }; @@ -558,6 +667,7 @@ protected: friend class ASTStmtReader; friend class ParenListExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// The number of expressions in the paren list. @@ -568,6 +678,7 @@ protected: friend class ASTStmtReader; friend class GenericSelectionExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// The location of the "_Generic". @@ -578,29 +689,31 @@ protected: friend class ASTStmtReader; // deserialization friend class PseudoObjectExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; - // These don't need to be particularly wide, because they're - // strictly limited by the forms of expressions we permit. - unsigned NumSubExprs : 8; - unsigned ResultIndex : 32 - 8 - NumExprBits; + unsigned NumSubExprs : 16; + unsigned ResultIndex : 16; }; class SourceLocExprBitfields { friend class ASTStmtReader; friend class SourceLocExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// The kind of source location builtin represented by the SourceLocExpr. - /// Ex. __builtin_LINE, __builtin_FUNCTION, ect. - unsigned Kind : 2; + /// Ex. __builtin_LINE, __builtin_FUNCTION, etc. + LLVM_PREFERRED_TYPE(SourceLocIdentKind) + unsigned Kind : 3; }; class StmtExprBitfields { friend class ASTStmtReader; friend class StmtExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// The number of levels of template parameters enclosing this statement @@ -615,10 +728,12 @@ protected: friend class ASTStmtReader; friend class CXXOperatorCallExpr; + LLVM_PREFERRED_TYPE(CallExprBitfields) unsigned : NumCallExprBits; /// The kind of this overloaded operator. One of the enumerator /// value of OverloadedOperatorKind. + LLVM_PREFERRED_TYPE(OverloadedOperatorKind) unsigned OperatorKind : 6; }; @@ -626,17 +741,21 @@ protected: friend class ASTStmtReader; friend class CXXRewrittenBinaryOperator; + LLVM_PREFERRED_TYPE(CallExprBitfields) unsigned : NumCallExprBits; + LLVM_PREFERRED_TYPE(bool) unsigned IsReversed : 1; }; class CXXBoolLiteralExprBitfields { friend class CXXBoolLiteralExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// The value of the boolean literal. + LLVM_PREFERRED_TYPE(bool) unsigned Value : 1; /// The location of the boolean literal. @@ -646,6 +765,7 @@ protected: class CXXNullPtrLiteralExprBitfields { friend class CXXNullPtrLiteralExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// The location of the null pointer literal. @@ -655,9 +775,11 @@ protected: class CXXThisExprBitfields { friend class CXXThisExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// Whether this is an implicit "this". + LLVM_PREFERRED_TYPE(bool) unsigned IsImplicit : 1; /// The location of the "this". @@ -668,9 +790,11 @@ protected: friend class ASTStmtReader; friend class CXXThrowExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// Whether the thrown variable (if any) is in scope. + LLVM_PREFERRED_TYPE(bool) unsigned IsThrownVariableInScope : 1; /// The location of the "throw". @@ -681,8 +805,13 @@ protected: friend class ASTStmtReader; friend class CXXDefaultArgExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; + /// Whether this CXXDefaultArgExpr rewrote its argument and stores a copy. + LLVM_PREFERRED_TYPE(bool) + unsigned HasRewrittenInit : 1; + /// The location where the default argument expression was used. SourceLocation Loc; }; @@ -691,8 +820,14 @@ protected: friend class ASTStmtReader; friend class CXXDefaultInitExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; + /// Whether this CXXDefaultInitExprBitfields rewrote its argument and stores + /// a copy. + LLVM_PREFERRED_TYPE(bool) + unsigned HasRewrittenInit : 1; + /// The location where the default initializer expression was used. SourceLocation Loc; }; @@ -701,6 +836,7 @@ protected: friend class ASTStmtReader; friend class CXXScalarValueInitExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; SourceLocation RParenLoc; @@ -711,28 +847,37 @@ protected: friend class ASTStmtWriter; friend class CXXNewExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// Was the usage ::new, i.e. is the global new to be used? + LLVM_PREFERRED_TYPE(bool) unsigned IsGlobalNew : 1; /// Do we allocate an array? If so, the first trailing "Stmt *" is the /// size expression. + LLVM_PREFERRED_TYPE(bool) unsigned IsArray : 1; /// Should the alignment be passed to the allocation function? + LLVM_PREFERRED_TYPE(bool) unsigned ShouldPassAlignment : 1; /// If this is an array allocation, does the usual deallocation /// function for the allocated type want to know the allocated size? + LLVM_PREFERRED_TYPE(bool) unsigned UsualArrayDeleteWantsSize : 1; - /// What kind of initializer do we have? Could be none, parens, or braces. - /// In storage, we distinguish between "none, and no initializer expr", and - /// "none, but an implicit initializer expr". + // Is initializer expr present? + LLVM_PREFERRED_TYPE(bool) + unsigned HasInitializer : 1; + + /// What kind of initializer syntax used? Could be none, parens, or braces. + LLVM_PREFERRED_TYPE(CXXNewInitializationStyle) unsigned StoredInitializationStyle : 2; /// True if the allocated type was expressed as a parenthesized type-id. + LLVM_PREFERRED_TYPE(bool) unsigned IsParenTypeId : 1; /// The number of placement new arguments. @@ -743,21 +888,26 @@ protected: friend class ASTStmtReader; friend class CXXDeleteExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// Is this a forced global delete, i.e. "::delete"? + LLVM_PREFERRED_TYPE(bool) unsigned GlobalDelete : 1; /// Is this the array form of delete, i.e. "delete[]"? + LLVM_PREFERRED_TYPE(bool) unsigned ArrayForm : 1; /// ArrayFormAsWritten can be different from ArrayForm if 'delete' is /// applied to pointer-to-array type (ArrayFormAsWritten will be false /// while ArrayForm will be true). + LLVM_PREFERRED_TYPE(bool) unsigned ArrayFormAsWritten : 1; /// Does the usual deallocation function for the element type require /// a size_t argument? + LLVM_PREFERRED_TYPE(bool) unsigned UsualArrayDeleteWantsSize : 1; /// Location of the expression. @@ -769,13 +919,16 @@ protected: friend class ASTStmtWriter; friend class TypeTraitExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// The kind of type trait, which is a value of a TypeTrait enumerator. + LLVM_PREFERRED_TYPE(TypeTrait) unsigned Kind : 8; /// If this expression is not value-dependent, this indicates whether /// the trait evaluated true or false. + LLVM_PREFERRED_TYPE(bool) unsigned Value : 1; /// The number of arguments to this type trait. According to [implimits] @@ -789,10 +942,12 @@ protected: friend class ASTStmtWriter; friend class DependentScopeDeclRefExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// Whether the name includes info for explicit template /// keyword and arguments. + LLVM_PREFERRED_TYPE(bool) unsigned HasTemplateKWAndArgsInfo : 1; }; @@ -800,14 +955,23 @@ protected: friend class ASTStmtReader; friend class CXXConstructExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; + LLVM_PREFERRED_TYPE(bool) unsigned Elidable : 1; + LLVM_PREFERRED_TYPE(bool) unsigned HadMultipleCandidates : 1; + LLVM_PREFERRED_TYPE(bool) unsigned ListInitialization : 1; + LLVM_PREFERRED_TYPE(bool) unsigned StdInitListInitialization : 1; + LLVM_PREFERRED_TYPE(bool) unsigned ZeroInitialization : 1; + LLVM_PREFERRED_TYPE(CXXConstructionKind) unsigned ConstructionKind : 3; + LLVM_PREFERRED_TYPE(bool) + unsigned IsImmediateEscalating : 1; SourceLocation Loc; }; @@ -816,9 +980,11 @@ protected: friend class ASTStmtReader; // deserialization friend class ExprWithCleanups; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; // When false, it must not have side effects. + LLVM_PREFERRED_TYPE(bool) unsigned CleanupsHaveSideEffects : 1; unsigned NumObjects : 32 - 1 - NumExprBits; @@ -828,6 +994,7 @@ protected: friend class ASTStmtReader; friend class CXXUnresolvedConstructExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// The number of arguments used to construct the type. @@ -838,18 +1005,22 @@ protected: friend class ASTStmtReader; friend class CXXDependentScopeMemberExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// Whether this member expression used the '->' operator or /// the '.' operator. + LLVM_PREFERRED_TYPE(bool) unsigned IsArrow : 1; /// Whether this member expression has info for explicit template /// keyword and arguments. + LLVM_PREFERRED_TYPE(bool) unsigned HasTemplateKWAndArgsInfo : 1; /// See getFirstQualifierFoundInScope() and the comment listing /// the trailing objects. + LLVM_PREFERRED_TYPE(bool) unsigned HasFirstQualifierFoundInScope : 1; /// The location of the '->' or '.' operator. @@ -860,10 +1031,12 @@ protected: friend class ASTStmtReader; friend class OverloadExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// Whether the name includes info for explicit template /// keyword and arguments. + LLVM_PREFERRED_TYPE(bool) unsigned HasTemplateKWAndArgsInfo : 1; /// Padding used by the derived classes to store various bits. If you @@ -880,14 +1053,17 @@ protected: friend class ASTStmtReader; friend class UnresolvedLookupExpr; + LLVM_PREFERRED_TYPE(OverloadExprBitfields) unsigned : NumOverloadExprBits; /// True if these lookup results should be extended by /// argument-dependent lookup if this is the operand of a function call. + LLVM_PREFERRED_TYPE(bool) unsigned RequiresADL : 1; /// True if these lookup results are overloaded. This is pretty trivially /// rederivable if we urgently need to kill this field. + LLVM_PREFERRED_TYPE(bool) unsigned Overloaded : 1; }; static_assert(sizeof(UnresolvedLookupExprBitfields) <= 4, @@ -898,13 +1074,16 @@ protected: friend class ASTStmtReader; friend class UnresolvedMemberExpr; + LLVM_PREFERRED_TYPE(OverloadExprBitfields) unsigned : NumOverloadExprBits; /// Whether this member expression used the '->' operator or /// the '.' operator. + LLVM_PREFERRED_TYPE(bool) unsigned IsArrow : 1; /// Whether the lookup results contain an unresolved using declaration. + LLVM_PREFERRED_TYPE(bool) unsigned HasUnresolvedUsing : 1; }; static_assert(sizeof(UnresolvedMemberExprBitfields) <= 4, @@ -915,8 +1094,10 @@ protected: friend class ASTStmtReader; friend class CXXNoexceptExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; + LLVM_PREFERRED_TYPE(bool) unsigned Value : 1; }; @@ -924,6 +1105,7 @@ protected: friend class ASTStmtReader; friend class SubstNonTypeTemplateParmExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// The location of the non-type template parameter reference. @@ -935,17 +1117,21 @@ protected: friend class ASTStmtWriter; friend class LambdaExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// The default capture kind, which is a value of type /// LambdaCaptureDefault. + LLVM_PREFERRED_TYPE(LambdaCaptureDefault) unsigned CaptureDefault : 2; /// Whether this lambda had an explicit parameter list vs. an /// implicit (and empty) parameter list. + LLVM_PREFERRED_TYPE(bool) unsigned ExplicitParams : 1; /// Whether this lambda had the result type explicitly specified. + LLVM_PREFERRED_TYPE(bool) unsigned ExplicitResultType : 1; /// The number of captures. @@ -957,19 +1143,23 @@ protected: friend class ASTStmtWriter; friend class RequiresExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; + LLVM_PREFERRED_TYPE(bool) unsigned IsSatisfied : 1; SourceLocation RequiresKWLoc; }; - //===--- C++ Coroutines TS bitfields classes ---===// + //===--- C++ Coroutines bitfields classes ---===// class CoawaitExprBitfields { friend class CoawaitExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; + LLVM_PREFERRED_TYPE(bool) unsigned IsImplicit : 1; }; @@ -978,8 +1168,10 @@ protected: class ObjCIndirectCopyRestoreExprBitfields { friend class ObjCIndirectCopyRestoreExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; + LLVM_PREFERRED_TYPE(bool) unsigned ShouldCopy : 1; }; @@ -989,10 +1181,12 @@ protected: friend class ASTStmtReader; friend class OpaqueValueExpr; + LLVM_PREFERRED_TYPE(ExprBitfields) unsigned : NumExprBits; /// The OVE is a unique semantic reference to its source expression if this /// bit is set to true. + LLVM_PREFERRED_TYPE(bool) unsigned IsUnique : 1; SourceLocation Loc; @@ -1067,7 +1261,7 @@ protected: LambdaExprBitfields LambdaExprBits; RequiresExprBitfields RequiresExprBits; - // C++ Coroutines TS expressions + // C++ Coroutines expressions CoawaitExprBitfields CoawaitBits; // Obj-C Expressions @@ -1215,6 +1409,11 @@ public: const PrintingPolicy &Policy, unsigned Indentation = 0, StringRef NewlineSymbol = "\n", const ASTContext *Context = nullptr) const; + void printPrettyControlled(raw_ostream &OS, PrinterHelper *Helper, + const PrintingPolicy &Policy, + unsigned Indentation = 0, + StringRef NewlineSymbol = "\n", + const ASTContext *Context = nullptr) const; /// Pretty-prints in JSON format. void printJson(raw_ostream &Out, PrinterHelper *Helper, @@ -1238,7 +1437,7 @@ public: } /// Child Iterators: All subclasses must implement 'children' - /// to permit easy iteration over the substatements/subexpessions of an + /// to permit easy iteration over the substatements/subexpressions of an /// AST node. This permits easy iteration over all nodes in the AST. using child_iterator = StmtIterator; using const_child_iterator = ConstStmtIterator; @@ -1271,8 +1470,13 @@ public: /// parameters are identified by index/level rather than their /// declaration pointers) or the exact representation of the statement as /// written in the source. + /// \param ProfileLambdaExpr whether or not to profile lambda expressions. + /// When false, the lambda expressions are never considered to be equal to + /// other lambda expressions. When true, the lambda expressions with the same + /// implementation will be considered to be the same. ProfileLambdaExpr should + /// only be true when we try to merge two declarations within modules. void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - bool Canonical) const; + bool Canonical, bool ProfileLambdaExpr = false) const; /// Calculate a unique representation for a statement that is /// stable across compiler invocations. @@ -1395,36 +1599,63 @@ public: }; /// CompoundStmt - This represents a group of statements like { stmt stmt }. -class CompoundStmt final : public Stmt, - private llvm::TrailingObjects<CompoundStmt, Stmt *> { +class CompoundStmt final + : public Stmt, + private llvm::TrailingObjects<CompoundStmt, Stmt *, FPOptionsOverride> { friend class ASTStmtReader; friend TrailingObjects; - /// The location of the closing "}". LBraceLoc is stored in CompoundStmtBits. + /// The location of the opening "{". + SourceLocation LBraceLoc; + + /// The location of the closing "}". SourceLocation RBraceLoc; - CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB, SourceLocation RB); + CompoundStmt(ArrayRef<Stmt *> Stmts, FPOptionsOverride FPFeatures, + SourceLocation LB, SourceLocation RB); explicit CompoundStmt(EmptyShell Empty) : Stmt(CompoundStmtClass, Empty) {} void setStmts(ArrayRef<Stmt *> Stmts); + /// Set FPOptionsOverride in trailing storage. Used only by Serialization. + void setStoredFPFeatures(FPOptionsOverride F) { + assert(hasStoredFPFeatures()); + *getTrailingObjects<FPOptionsOverride>() = F; + } + + size_t numTrailingObjects(OverloadToken<Stmt *>) const { + return CompoundStmtBits.NumStmts; + } + public: static CompoundStmt *Create(const ASTContext &C, ArrayRef<Stmt *> Stmts, - SourceLocation LB, SourceLocation RB); + FPOptionsOverride FPFeatures, SourceLocation LB, + SourceLocation RB); // Build an empty compound statement with a location. - explicit CompoundStmt(SourceLocation Loc) - : Stmt(CompoundStmtClass), RBraceLoc(Loc) { + explicit CompoundStmt(SourceLocation Loc) : CompoundStmt(Loc, Loc) {} + + CompoundStmt(SourceLocation Loc, SourceLocation EndLoc) + : Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(EndLoc) { CompoundStmtBits.NumStmts = 0; - CompoundStmtBits.LBraceLoc = Loc; + CompoundStmtBits.HasFPFeatures = 0; } // Build an empty compound statement. - static CompoundStmt *CreateEmpty(const ASTContext &C, unsigned NumStmts); + static CompoundStmt *CreateEmpty(const ASTContext &C, unsigned NumStmts, + bool HasFPFeatures); bool body_empty() const { return CompoundStmtBits.NumStmts == 0; } unsigned size() const { return CompoundStmtBits.NumStmts; } + bool hasStoredFPFeatures() const { return CompoundStmtBits.HasFPFeatures; } + + /// Get FPOptionsOverride from trailing storage. + FPOptionsOverride getStoredFPFeatures() const { + assert(hasStoredFPFeatures()); + return *getTrailingObjects<FPOptionsOverride>(); + } + using body_iterator = Stmt **; using body_range = llvm::iterator_range<body_iterator>; @@ -1499,10 +1730,10 @@ public: return const_cast<CompoundStmt *>(this)->getStmtExprResult(); } - SourceLocation getBeginLoc() const { return CompoundStmtBits.LBraceLoc; } + SourceLocation getBeginLoc() const { return LBraceLoc; } SourceLocation getEndLoc() const { return RBraceLoc; } - SourceLocation getLBracLoc() const { return CompoundStmtBits.LBraceLoc; } + SourceLocation getLBracLoc() const { return LBraceLoc; } SourceLocation getRBracLoc() const { return RBraceLoc; } static bool classof(const Stmt *T) { @@ -1879,7 +2110,7 @@ public: SourceLocation getAttrLoc() const { return AttributedStmtBits.AttrLoc; } ArrayRef<const Attr *> getAttrs() const { - return llvm::makeArrayRef(getAttrArrayPtr(), AttributedStmtBits.NumAttrs); + return llvm::ArrayRef(getAttrArrayPtr(), AttributedStmtBits.NumAttrs); } Stmt *getSubStmt() { return SubStmt; } @@ -1950,8 +2181,8 @@ class IfStmt final unsigned elseOffset() const { return condOffset() + ElseOffsetFromCond; } /// Build an if/then/else statement. - IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr, Stmt *Init, - VarDecl *Var, Expr *Cond, SourceLocation LParenLoc, + IfStmt(const ASTContext &Ctx, SourceLocation IL, IfStatementKind Kind, + Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LParenLoc, SourceLocation RParenLoc, Stmt *Then, SourceLocation EL, Stmt *Else); /// Build an empty if/then/else statement. @@ -1960,9 +2191,9 @@ class IfStmt final public: /// Create an IfStmt. static IfStmt *Create(const ASTContext &Ctx, SourceLocation IL, - bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond, - SourceLocation LPL, SourceLocation RPL, Stmt *Then, - SourceLocation EL = SourceLocation(), + IfStatementKind Kind, Stmt *Init, VarDecl *Var, + Expr *Cond, SourceLocation LPL, SourceLocation RPL, + Stmt *Then, SourceLocation EL = SourceLocation(), Stmt *Else = nullptr); /// Create an empty IfStmt optionally with storage for an else statement, @@ -2047,6 +2278,11 @@ public: : nullptr; } + void setConditionVariableDeclStmt(DeclStmt *CondVar) { + assert(hasVarStorage()); + getTrailingObjects<Stmt *>()[varOffset()] = CondVar; + } + Stmt *getInit() { return hasInitStorage() ? getTrailingObjects<Stmt *>()[initOffset()] : nullptr; @@ -2077,13 +2313,35 @@ public: *getTrailingObjects<SourceLocation>() = ElseLoc; } - bool isConstexpr() const { return IfStmtBits.IsConstexpr; } - void setConstexpr(bool C) { IfStmtBits.IsConstexpr = C; } + bool isConsteval() const { + return getStatementKind() == IfStatementKind::ConstevalNonNegated || + getStatementKind() == IfStatementKind::ConstevalNegated; + } + + bool isNonNegatedConsteval() const { + return getStatementKind() == IfStatementKind::ConstevalNonNegated; + } + + bool isNegatedConsteval() const { + return getStatementKind() == IfStatementKind::ConstevalNegated; + } + + bool isConstexpr() const { + return getStatementKind() == IfStatementKind::Constexpr; + } + + void setStatementKind(IfStatementKind Kind) { + IfStmtBits.Kind = static_cast<unsigned>(Kind); + } + + IfStatementKind getStatementKind() const { + return static_cast<IfStatementKind>(IfStmtBits.Kind); + } /// If this is an 'if constexpr', determine which substatement will be taken. - /// Otherwise, or if the condition is value-dependent, returns None. - Optional<const Stmt*> getNondiscardedCase(const ASTContext &Ctx) const; - Optional<Stmt *> getNondiscardedCase(const ASTContext &Ctx); + /// Otherwise, or if the condition is value-dependent, returns std::nullopt. + std::optional<const Stmt *> getNondiscardedCase(const ASTContext &Ctx) const; + std::optional<Stmt *> getNondiscardedCase(const ASTContext &Ctx); bool isObjCAvailabilityCheck() const; @@ -2101,13 +2359,19 @@ public: // Iterators over subexpressions. The iterators will include iterating // over the initialization expression referenced by the condition variable. child_range children() { - return child_range(getTrailingObjects<Stmt *>(), + // We always store a condition, but there is none for consteval if + // statements, so skip it. + return child_range(getTrailingObjects<Stmt *>() + + (isConsteval() ? thenOffset() : 0), getTrailingObjects<Stmt *>() + numTrailingObjects(OverloadToken<Stmt *>())); } const_child_range children() const { - return const_child_range(getTrailingObjects<Stmt *>(), + // We always store a condition, but there is none for consteval if + // statements, so skip it. + return const_child_range(getTrailingObjects<Stmt *>() + + (isConsteval() ? thenOffset() : 0), getTrailingObjects<Stmt *>() + numTrailingObjects(OverloadToken<Stmt *>())); } @@ -2251,6 +2515,11 @@ public: : nullptr; } + void setConditionVariableDeclStmt(DeclStmt *CondVar) { + assert(hasVarStorage()); + getTrailingObjects<Stmt *>()[varOffset()] = CondVar; + } + SwitchCase *getSwitchCaseList() { return FirstCase; } const SwitchCase *getSwitchCaseList() const { return FirstCase; } void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; } @@ -2414,6 +2683,11 @@ public: : nullptr; } + void setConditionVariableDeclStmt(DeclStmt *CondVar) { + assert(hasVarStorage()); + getTrailingObjects<Stmt *>()[varOffset()] = CondVar; + } + SourceLocation getWhileLoc() const { return WhileStmtBits.WhileLoc; } void setWhileLoc(SourceLocation L) { WhileStmtBits.WhileLoc = L; } @@ -2503,6 +2777,8 @@ public: /// the init/cond/inc parts of the ForStmt will be null if they were not /// specified in the source. class ForStmt : public Stmt { + friend class ASTStmtReader; + enum { INIT, CONDVAR, COND, INC, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt. SourceLocation LParenLoc, RParenLoc; @@ -2530,10 +2806,18 @@ public: /// If this ForStmt has a condition variable, return the faux DeclStmt /// associated with the creation of that condition variable. + DeclStmt *getConditionVariableDeclStmt() { + return reinterpret_cast<DeclStmt*>(SubExprs[CONDVAR]); + } + const DeclStmt *getConditionVariableDeclStmt() const { return reinterpret_cast<DeclStmt*>(SubExprs[CONDVAR]); } + void setConditionVariableDeclStmt(DeclStmt *CondVar) { + SubExprs[CONDVAR] = CondVar; + } + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); } Stmt *getBody() { return SubExprs[BODY]; } @@ -3262,16 +3546,16 @@ public: //===--- Other ---===// ArrayRef<StringRef> getAllConstraints() const { - return llvm::makeArrayRef(Constraints, NumInputs + NumOutputs); + return llvm::ArrayRef(Constraints, NumInputs + NumOutputs); } ArrayRef<StringRef> getClobbers() const { - return llvm::makeArrayRef(Clobbers, NumClobbers); + return llvm::ArrayRef(Clobbers, NumClobbers); } ArrayRef<Expr*> getAllExprs() const { - return llvm::makeArrayRef(reinterpret_cast<Expr**>(Exprs), - NumInputs + NumOutputs); + return llvm::ArrayRef(reinterpret_cast<Expr **>(Exprs), + NumInputs + NumOutputs); } StringRef getClobber(unsigned i) const { return getClobbers()[i]; } @@ -3485,8 +3769,11 @@ public: llvm::PointerIntPair<VarDecl *, 2, VariableCaptureKind> VarAndKind; SourceLocation Loc; + Capture() = default; + public: friend class ASTStmtReader; + friend class CapturedStmt; /// Create a new capture. /// diff --git a/contrib/llvm-project/clang/include/clang/AST/StmtCXX.h b/contrib/llvm-project/clang/include/clang/AST/StmtCXX.h index 4d1f3e8ef255..8b4ef24ed376 100644 --- a/contrib/llvm-project/clang/include/clang/AST/StmtCXX.h +++ b/contrib/llvm-project/clang/include/clang/AST/StmtCXX.h @@ -75,7 +75,8 @@ class CXXTryStmt final : public Stmt, unsigned NumHandlers; size_t numTrailingObjects(OverloadToken<Stmt *>) const { return NumHandlers; } - CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers); + CXXTryStmt(SourceLocation tryLoc, CompoundStmt *tryBlock, + ArrayRef<Stmt *> handlers); CXXTryStmt(EmptyShell Empty, unsigned numHandlers) : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } @@ -84,7 +85,7 @@ class CXXTryStmt final : public Stmt, public: static CXXTryStmt *Create(const ASTContext &C, SourceLocation tryLoc, - Stmt *tryBlock, ArrayRef<Stmt*> handlers); + CompoundStmt *tryBlock, ArrayRef<Stmt *> handlers); static CXXTryStmt *Create(const ASTContext &C, EmptyShell Empty, unsigned numHandlers); @@ -326,8 +327,8 @@ class CoroutineBodyStmt final OnFallthrough, ///< Handler for control flow falling off the body. Allocate, ///< Coroutine frame memory allocation. Deallocate, ///< Coroutine frame memory deallocation. - ReturnValue, ///< Return value for thunk function: p.get_return_object(). ResultDecl, ///< Declaration holding the result of get_return_object. + ReturnValue, ///< Return value for thunk function: p.get_return_object(). ReturnStmt, ///< Return statement for the thunk function. ReturnStmtOnAllocFailure, ///< Return statement if allocation failed. FirstParamMove ///< First offset for move construction of parameter copies. @@ -353,8 +354,8 @@ public: Stmt *OnFallthrough = nullptr; Expr *Allocate = nullptr; Expr *Deallocate = nullptr; - Expr *ReturnValue = nullptr; Stmt *ResultDecl = nullptr; + Expr *ReturnValue = nullptr; Stmt *ReturnStmt = nullptr; Stmt *ReturnStmtOnAllocFailure = nullptr; ArrayRef<Stmt *> ParamMoves; @@ -374,9 +375,10 @@ public: } /// Retrieve the body of the coroutine as written. This will be either - /// a CompoundStmt or a TryStmt. - Stmt *getBody() const { - return getStoredStmts()[SubStmt::Body]; + /// a CompoundStmt. If the coroutine is in function-try-block, we will + /// wrap the CXXTryStmt into a CompoundStmt to keep consistency. + CompoundStmt *getBody() const { + return cast<CompoundStmt>(getStoredStmts()[SubStmt::Body]); } Stmt *getPromiseDeclStmt() const { @@ -406,10 +408,14 @@ public: Expr *getDeallocate() const { return cast_or_null<Expr>(getStoredStmts()[SubStmt::Deallocate]); } + Stmt *getResultDecl() const { return getStoredStmts()[SubStmt::ResultDecl]; } Expr *getReturnValueInit() const { return cast<Expr>(getStoredStmts()[SubStmt::ReturnValue]); } - Stmt *getResultDecl() const { return getStoredStmts()[SubStmt::ResultDecl]; } + Expr *getReturnValue() const { + auto *RS = dyn_cast_or_null<clang::ReturnStmt>(getReturnStmt()); + return RS ? RS->getRetValue() : nullptr; + } Stmt *getReturnStmt() const { return getStoredStmts()[SubStmt::ReturnStmt]; } Stmt *getReturnStmtOnAllocFailure() const { return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure]; @@ -437,6 +443,17 @@ public: NumParams); } + child_range childrenExclBody() { + return child_range(getStoredStmts() + SubStmt::Body + 1, + getStoredStmts() + SubStmt::FirstParamMove + NumParams); + } + + const_child_range childrenExclBody() const { + return const_child_range(getStoredStmts() + SubStmt::Body + 1, + getStoredStmts() + SubStmt::FirstParamMove + + NumParams); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == CoroutineBodyStmtClass; } @@ -495,16 +512,10 @@ public: } child_range children() { - if (!getOperand()) - return child_range(SubStmts + SubStmt::PromiseCall, - SubStmts + SubStmt::Count); return child_range(SubStmts, SubStmts + SubStmt::Count); } const_child_range children() const { - if (!getOperand()) - return const_child_range(SubStmts + SubStmt::PromiseCall, - SubStmts + SubStmt::Count); return const_child_range(SubStmts, SubStmts + SubStmt::Count); } diff --git a/contrib/llvm-project/clang/include/clang/AST/StmtObjC.h b/contrib/llvm-project/clang/include/clang/AST/StmtObjC.h index 948ef2421cb9..c46ff4634c82 100644 --- a/contrib/llvm-project/clang/include/clang/AST/StmtObjC.h +++ b/contrib/llvm-project/clang/include/clang/AST/StmtObjC.h @@ -162,8 +162,14 @@ public: }; /// Represents Objective-C's \@try ... \@catch ... \@finally statement. -class ObjCAtTryStmt : public Stmt { -private: +class ObjCAtTryStmt final + : public Stmt, + private llvm::TrailingObjects<ObjCAtTryStmt, Stmt *> { + friend TrailingObjects; + size_t numTrailingObjects(OverloadToken<Stmt *>) const { + return 1 + NumCatchStmts + HasFinally; + } + // The location of the @ in the \@try. SourceLocation AtTryLoc; @@ -178,10 +184,8 @@ private: /// The order of the statements in memory follows the order in the source, /// with the \@try body first, followed by the \@catch statements (if any) /// and, finally, the \@finally (if it exists). - Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); } - const Stmt* const *getStmts() const { - return reinterpret_cast<const Stmt * const*> (this + 1); - } + Stmt **getStmts() { return getTrailingObjects<Stmt *>(); } + Stmt *const *getStmts() const { return getTrailingObjects<Stmt *>(); } ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, Stmt **CatchStmts, unsigned NumCatchStmts, @@ -257,13 +261,34 @@ public: } child_range children() { - return child_range(getStmts(), - getStmts() + 1 + NumCatchStmts + HasFinally); + return child_range( + getStmts(), getStmts() + numTrailingObjects(OverloadToken<Stmt *>())); } const_child_range children() const { return const_child_range(const_cast<ObjCAtTryStmt *>(this)->children()); } + + using catch_stmt_iterator = CastIterator<ObjCAtCatchStmt>; + using const_catch_stmt_iterator = ConstCastIterator<ObjCAtCatchStmt>; + using catch_range = llvm::iterator_range<catch_stmt_iterator>; + using catch_const_range = llvm::iterator_range<const_catch_stmt_iterator>; + + catch_stmt_iterator catch_stmts_begin() { return getStmts() + 1; } + catch_stmt_iterator catch_stmts_end() { + return catch_stmts_begin() + NumCatchStmts; + } + catch_range catch_stmts() { + return catch_range(catch_stmts_begin(), catch_stmts_end()); + } + + const_catch_stmt_iterator catch_stmts_begin() const { return getStmts() + 1; } + const_catch_stmt_iterator catch_stmts_end() const { + return catch_stmts_begin() + NumCatchStmts; + } + catch_const_range catch_stmts() const { + return catch_const_range(catch_stmts_begin(), catch_stmts_end()); + } }; /// Represents Objective-C's \@synchronized statement. diff --git a/contrib/llvm-project/clang/include/clang/AST/StmtOpenMP.h b/contrib/llvm-project/clang/include/clang/AST/StmtOpenMP.h index 9c85df741f48..621643391535 100644 --- a/contrib/llvm-project/clang/include/clang/AST/StmtOpenMP.h +++ b/contrib/llvm-project/clang/include/clang/AST/StmtOpenMP.h @@ -277,10 +277,19 @@ class OMPExecutableDirective : public Stmt { /// Get the clauses storage. MutableArrayRef<OMPClause *> getClauses() { if (!Data) - return llvm::None; + return std::nullopt; return Data->getClauses(); } + /// Was this directive mapped from an another directive? + /// e.g. 1) omp loop bind(parallel) is mapped to OMPD_for + /// 2) omp loop bind(teams) is mapped to OMPD_distribute + /// 3) omp loop bind(thread) is mapped to OMPD_simd + /// It was necessary to note it down in the Directive because of + /// clang::TreeTransform::TransformOMPExecutableDirective() pass in + /// the frontend. + OpenMPDirectiveKind PrevMappedDirective = llvm::omp::OMPD_unknown; + protected: /// Data, associated with the directive. OMPChildren *Data = nullptr; @@ -345,6 +354,10 @@ protected: return Inst; } + void setMappedDirective(OpenMPDirectiveKind MappedDirective) { + PrevMappedDirective = MappedDirective; + } + public: /// Iterates over expressions/statements used in the construct. class used_clauses_child_iterator @@ -399,8 +412,9 @@ public: static llvm::iterator_range<used_clauses_child_iterator> used_clauses_children(ArrayRef<OMPClause *> Clauses) { - return {used_clauses_child_iterator(Clauses), - used_clauses_child_iterator(llvm::makeArrayRef(Clauses.end(), 0))}; + return { + used_clauses_child_iterator(Clauses), + used_clauses_child_iterator(llvm::ArrayRef(Clauses.end(), (size_t)0))}; } /// Iterates over a filtered subrange of clauses applied to a @@ -445,7 +459,7 @@ public: getClausesOfKind(ArrayRef<OMPClause *> Clauses) { return {specific_clause_iterator<SpecificClause>(Clauses), specific_clause_iterator<SpecificClause>( - llvm::makeArrayRef(Clauses.end(), 0))}; + llvm::ArrayRef(Clauses.end(), (size_t)0))}; } template <typename SpecificClause> @@ -571,7 +585,7 @@ public: ArrayRef<OMPClause *> clauses() const { if (!Data) - return llvm::None; + return std::nullopt; return Data->getClauses(); } @@ -597,6 +611,8 @@ public: "Expected directive with the associated statement."); return Data->getRawStmt(); } + + OpenMPDirectiveKind getMappedDirective() const { return PrevMappedDirective; } }; /// This represents '#pragma omp parallel' directive. @@ -889,22 +905,23 @@ public: /// Calls the specified callback function for all the loops in \p CurStmt, /// from the outermost to the innermost. - static bool doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops, - unsigned NumLoops, - llvm::function_ref<bool(unsigned, Stmt *)> Callback, - llvm::function_ref<void(OMPLoopBasedDirective *)> - OnTransformationCallback); + static bool + doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops, + unsigned NumLoops, + llvm::function_ref<bool(unsigned, Stmt *)> Callback, + llvm::function_ref<void(OMPLoopTransformationDirective *)> + OnTransformationCallback); static bool doForAllLoops(const Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops, llvm::function_ref<bool(unsigned, const Stmt *)> Callback, - llvm::function_ref<void(const OMPLoopBasedDirective *)> + llvm::function_ref<void(const OMPLoopTransformationDirective *)> OnTransformationCallback) { auto &&NewCallback = [Callback](unsigned Cnt, Stmt *CurStmt) { return Callback(Cnt, CurStmt); }; auto &&NewTransformCb = - [OnTransformationCallback](OMPLoopBasedDirective *A) { + [OnTransformationCallback](OMPLoopTransformationDirective *A) { OnTransformationCallback(A); }; return doForAllLoops(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops, @@ -917,7 +934,7 @@ public: doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops, llvm::function_ref<bool(unsigned, Stmt *)> Callback) { - auto &&TransformCb = [](OMPLoopBasedDirective *) {}; + auto &&TransformCb = [](OMPLoopTransformationDirective *) {}; return doForAllLoops(CurStmt, TryImperfectlyNestedLoops, NumLoops, Callback, TransformCb); } @@ -954,6 +971,47 @@ public: } }; +/// The base class for all loop transformation directives. +class OMPLoopTransformationDirective : public OMPLoopBasedDirective { + friend class ASTStmtReader; + + /// Number of loops generated by this loop transformation. + unsigned NumGeneratedLoops = 0; + +protected: + explicit OMPLoopTransformationDirective(StmtClass SC, + OpenMPDirectiveKind Kind, + SourceLocation StartLoc, + SourceLocation EndLoc, + unsigned NumAssociatedLoops) + : OMPLoopBasedDirective(SC, Kind, StartLoc, EndLoc, NumAssociatedLoops) {} + + /// Set the number of loops generated by this loop transformation. + void setNumGeneratedLoops(unsigned Num) { NumGeneratedLoops = Num; } + +public: + /// Return the number of associated (consumed) loops. + unsigned getNumAssociatedLoops() const { return getLoopsNumber(); } + + /// Return the number of loops generated by this loop transformation. + unsigned getNumGeneratedLoops() const { return NumGeneratedLoops; } + + /// Get the de-sugared statements after the loop transformation. + /// + /// Might be nullptr if either the directive generates no loops and is handled + /// directly in CodeGen, or resolving a template-dependence context is + /// required. + Stmt *getTransformedStmt() const; + + /// Return preinits statement. + Stmt *getPreInits() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTileDirectiveClass || + T->getStmtClass() == OMPUnrollDirectiveClass; + } +}; + /// This is a common base class for loop directives ('omp simd', 'omp /// for', 'omp for simd' etc.). It is responsible for the loop code generation. /// @@ -1024,7 +1082,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective { MutableArrayRef<Expr *> getCounters() { auto **Storage = reinterpret_cast<Expr **>( &Data->getChildren()[getArraysOffset(getDirectiveKind())]); - return llvm::makeMutableArrayRef(Storage, getLoopsNumber()); + return llvm::MutableArrayRef(Storage, getLoopsNumber()); } /// Get the private counters storage. @@ -1032,7 +1090,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective { auto **Storage = reinterpret_cast<Expr **>( &Data->getChildren()[getArraysOffset(getDirectiveKind()) + getLoopsNumber()]); - return llvm::makeMutableArrayRef(Storage, getLoopsNumber()); + return llvm::MutableArrayRef(Storage, getLoopsNumber()); } /// Get the updates storage. @@ -1040,7 +1098,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective { auto **Storage = reinterpret_cast<Expr **>( &Data->getChildren()[getArraysOffset(getDirectiveKind()) + 2 * getLoopsNumber()]); - return llvm::makeMutableArrayRef(Storage, getLoopsNumber()); + return llvm::MutableArrayRef(Storage, getLoopsNumber()); } /// Get the updates storage. @@ -1048,7 +1106,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective { auto **Storage = reinterpret_cast<Expr **>( &Data->getChildren()[getArraysOffset(getDirectiveKind()) + 3 * getLoopsNumber()]); - return llvm::makeMutableArrayRef(Storage, getLoopsNumber()); + return llvm::MutableArrayRef(Storage, getLoopsNumber()); } /// Get the final counter updates storage. @@ -1056,7 +1114,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective { auto **Storage = reinterpret_cast<Expr **>( &Data->getChildren()[getArraysOffset(getDirectiveKind()) + 4 * getLoopsNumber()]); - return llvm::makeMutableArrayRef(Storage, getLoopsNumber()); + return llvm::MutableArrayRef(Storage, getLoopsNumber()); } /// Get the dependent counters storage. @@ -1064,7 +1122,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective { auto **Storage = reinterpret_cast<Expr **>( &Data->getChildren()[getArraysOffset(getDirectiveKind()) + 5 * getLoopsNumber()]); - return llvm::makeMutableArrayRef(Storage, getLoopsNumber()); + return llvm::MutableArrayRef(Storage, getLoopsNumber()); } /// Get the dependent inits storage. @@ -1072,7 +1130,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective { auto **Storage = reinterpret_cast<Expr **>( &Data->getChildren()[getArraysOffset(getDirectiveKind()) + 6 * getLoopsNumber()]); - return llvm::makeMutableArrayRef(Storage, getLoopsNumber()); + return llvm::MutableArrayRef(Storage, getLoopsNumber()); } /// Get the finals conditions storage. @@ -1080,7 +1138,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective { auto **Storage = reinterpret_cast<Expr **>( &Data->getChildren()[getArraysOffset(getDirectiveKind()) + 7 * getLoopsNumber()]); - return llvm::makeMutableArrayRef(Storage, getLoopsNumber()); + return llvm::MutableArrayRef(Storage, getLoopsNumber()); } protected: @@ -1102,7 +1160,7 @@ protected: if (isOpenMPLoopBoundSharingDirective(Kind)) return CombinedDistributeEnd; if (isOpenMPWorksharingDirective(Kind) || isOpenMPTaskLoopDirective(Kind) || - isOpenMPDistributeDirective(Kind)) + isOpenMPGenericLoopDirective(Kind) || isOpenMPDistributeDirective(Kind)) return WorksharingEnd; return DefaultEnd; } @@ -1134,6 +1192,7 @@ protected: } void setIsLastIterVariable(Expr *IL) { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1141,6 +1200,7 @@ protected: } void setLowerBoundVariable(Expr *LB) { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1148,6 +1208,7 @@ protected: } void setUpperBoundVariable(Expr *UB) { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1155,6 +1216,7 @@ protected: } void setStrideVariable(Expr *ST) { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1162,6 +1224,7 @@ protected: } void setEnsureUpperBound(Expr *EUB) { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1169,6 +1232,7 @@ protected: } void setNextLowerBound(Expr *NLB) { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1176,6 +1240,7 @@ protected: } void setNextUpperBound(Expr *NUB) { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1183,6 +1248,7 @@ protected: } void setNumIterations(Expr *NI) { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1285,6 +1351,7 @@ public: Stmt *getPreInits() { return Data->getChildren()[PreInitsOffset]; } Expr *getIsLastIterVariable() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1292,6 +1359,7 @@ public: } Expr *getLowerBoundVariable() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1299,6 +1367,7 @@ public: } Expr *getUpperBoundVariable() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1306,6 +1375,7 @@ public: } Expr *getStrideVariable() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1313,6 +1383,7 @@ public: } Expr *getEnsureUpperBound() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1320,6 +1391,7 @@ public: } Expr *getNextLowerBound() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1327,6 +1399,7 @@ public: } Expr *getNextUpperBound() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1334,6 +1407,7 @@ public: } Expr *getNumIterations() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPGenericLoopDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); @@ -1465,8 +1539,17 @@ public: T->getStmtClass() == OMPParallelForSimdDirectiveClass || T->getStmtClass() == OMPTaskLoopDirectiveClass || T->getStmtClass() == OMPTaskLoopSimdDirectiveClass || + T->getStmtClass() == OMPMaskedTaskLoopDirectiveClass || + T->getStmtClass() == OMPMaskedTaskLoopSimdDirectiveClass || T->getStmtClass() == OMPMasterTaskLoopDirectiveClass || T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass || + T->getStmtClass() == OMPGenericLoopDirectiveClass || + T->getStmtClass() == OMPTeamsGenericLoopDirectiveClass || + T->getStmtClass() == OMPTargetTeamsGenericLoopDirectiveClass || + T->getStmtClass() == OMPParallelGenericLoopDirectiveClass || + T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass || + T->getStmtClass() == OMPParallelMaskedTaskLoopDirectiveClass || + T->getStmtClass() == OMPParallelMaskedTaskLoopSimdDirectiveClass || T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass || T->getStmtClass() == OMPParallelMasterTaskLoopSimdDirectiveClass || T->getStmtClass() == OMPDistributeDirectiveClass || @@ -1536,7 +1619,8 @@ public: SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, - const HelperExprs &Exprs); + const HelperExprs &Exprs, + OpenMPDirectiveKind ParamPrevMappedDirective); /// Creates an empty directive with the place /// for \a NumClauses clauses. @@ -1614,7 +1698,8 @@ public: SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, - Expr *TaskRedRef, bool HasCancel); + Expr *TaskRedRef, bool HasCancel, + OpenMPDirectiveKind ParamPrevMappedDirective); /// Creates an empty directive with the place /// for \a NumClauses clauses. @@ -1846,6 +1931,57 @@ public: } }; +/// This represents '#pragma omp scope' directive. +/// \code +/// #pragma omp scope private(a,b) nowait +/// \endcode +/// In this example directive '#pragma omp scope' has clauses 'private' with +/// the variables 'a' and 'b' and nowait. +/// +class OMPScopeDirective final : public OMPExecutableDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPScopeDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(OMPScopeDirectiveClass, llvm::omp::OMPD_scope, + StartLoc, EndLoc) {} + + /// Build an empty directive. + /// + explicit OMPScopeDirective() + : OMPExecutableDirective(OMPScopeDirectiveClass, llvm::omp::OMPD_scope, + SourceLocation(), SourceLocation()) {} + +public: + /// Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPScopeDirective *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt); + + /// Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPScopeDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPScopeDirectiveClass; + } +}; + /// This represents '#pragma omp single' directive. /// /// \code @@ -2241,6 +2377,69 @@ public: } }; +/// This represents '#pragma omp parallel masked' directive. +/// +/// \code +/// #pragma omp parallel masked filter(tid) +/// \endcode +/// In this example directive '#pragma omp parallel masked' has a clause +/// 'filter' with the variable tid +/// +class OMPParallelMaskedDirective final : public OMPExecutableDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + + OMPParallelMaskedDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(OMPParallelMaskedDirectiveClass, + llvm::omp::OMPD_parallel_masked, StartLoc, + EndLoc) {} + + explicit OMPParallelMaskedDirective() + : OMPExecutableDirective(OMPParallelMaskedDirectiveClass, + llvm::omp::OMPD_parallel_masked, + SourceLocation(), SourceLocation()) {} + + /// Sets special task reduction descriptor. + void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; } + +public: + /// Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param TaskRedRef Task reduction special reference expression to handle + /// taskgroup descriptor. + /// + static OMPParallelMaskedDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef); + + /// Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPParallelMaskedDirective * + CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + + /// Returns special task reduction reference expression. + Expr *getTaskReductionRefExpr() { + return cast_or_null<Expr>(Data->getChildren()[0]); + } + const Expr *getTaskReductionRefExpr() const { + return const_cast<OMPParallelMaskedDirective *>(this) + ->getTaskReductionRefExpr(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPParallelMaskedDirectiveClass; + } +}; + /// This represents '#pragma omp parallel sections' directive. /// /// \code @@ -2510,15 +2709,20 @@ public: /// \param C AST context. /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. /// - static OMPTaskwaitDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); + static OMPTaskwaitDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses); /// Creates an empty directive. /// /// \param C AST context. + /// \param NumClauses Number of clauses. /// - static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C, EmptyShell); + static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); static bool classof(const Stmt *T) { return T->getStmtClass() == OMPTaskwaitDirectiveClass; @@ -2738,7 +2942,7 @@ public: /// /// \param C AST context. /// \param NumClauses Number of clauses. - /// \param IsStandalone true, if the the standalone directive is created. + /// \param IsStandalone true, if the standalone directive is created. /// static OMPOrderedDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, @@ -2759,25 +2963,31 @@ public: class OMPAtomicDirective : public OMPExecutableDirective { friend class ASTStmtReader; friend class OMPExecutableDirective; - /// Used for 'atomic update' or 'atomic capture' constructs. They may - /// have atomic expressions of forms - /// \code - /// x = x binop expr; - /// x = expr binop x; - /// \endcode - /// This field is true for the first form of the expression and false for the - /// second. Required for correct codegen of non-associative operations (like - /// << or >>). - bool IsXLHSInRHSPart = false; - /// Used for 'atomic update' or 'atomic capture' constructs. They may - /// have atomic expressions of forms - /// \code - /// v = x; <update x>; - /// <update x>; v = x; - /// \endcode - /// This field is true for the first(postfix) form of the expression and false - /// otherwise. - bool IsPostfixUpdate = false; + + struct FlagTy { + /// Used for 'atomic update' or 'atomic capture' constructs. They may + /// have atomic expressions of forms: + /// \code + /// x = x binop expr; + /// x = expr binop x; + /// \endcode + /// This field is 1 for the first form of the expression and 0 for the + /// second. Required for correct codegen of non-associative operations (like + /// << or >>). + uint8_t IsXLHSInRHSPart : 1; + /// Used for 'atomic update' or 'atomic capture' constructs. They may + /// have atomic expressions of forms: + /// \code + /// v = x; <update x>; + /// <update x>; v = x; + /// \endcode + /// This field is 1 for the first(postfix) form of the expression and 0 + /// otherwise. + uint8_t IsPostfixUpdate : 1; + /// 1 if 'v' is updated only when the condition is false (compare capture + /// only). + uint8_t IsFailOnly : 1; + } Flags; /// Build directive with the given start and end location. /// @@ -2794,18 +3004,62 @@ class OMPAtomicDirective : public OMPExecutableDirective { : OMPExecutableDirective(OMPAtomicDirectiveClass, llvm::omp::OMPD_atomic, SourceLocation(), SourceLocation()) {} + enum DataPositionTy : size_t { + POS_X = 0, + POS_V, + POS_E, + POS_UpdateExpr, + POS_D, + POS_Cond, + POS_R, + }; + /// Set 'x' part of the associated expression/statement. - void setX(Expr *X) { Data->getChildren()[0] = X; } + void setX(Expr *X) { Data->getChildren()[DataPositionTy::POS_X] = X; } /// Set helper expression of the form /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. - void setUpdateExpr(Expr *UE) { Data->getChildren()[1] = UE; } + void setUpdateExpr(Expr *UE) { + Data->getChildren()[DataPositionTy::POS_UpdateExpr] = UE; + } /// Set 'v' part of the associated expression/statement. - void setV(Expr *V) { Data->getChildren()[2] = V; } + void setV(Expr *V) { Data->getChildren()[DataPositionTy::POS_V] = V; } + /// Set 'r' part of the associated expression/statement. + void setR(Expr *R) { Data->getChildren()[DataPositionTy::POS_R] = R; } /// Set 'expr' part of the associated expression/statement. - void setExpr(Expr *E) { Data->getChildren()[3] = E; } + void setExpr(Expr *E) { Data->getChildren()[DataPositionTy::POS_E] = E; } + /// Set 'd' part of the associated expression/statement. + void setD(Expr *D) { Data->getChildren()[DataPositionTy::POS_D] = D; } + /// Set conditional expression in `atomic compare`. + void setCond(Expr *C) { Data->getChildren()[DataPositionTy::POS_Cond] = C; } public: + struct Expressions { + /// 'x' part of the associated expression/statement. + Expr *X = nullptr; + /// 'v' part of the associated expression/statement. + Expr *V = nullptr; + // 'r' part of the associated expression/statement. + Expr *R = nullptr; + /// 'expr' part of the associated expression/statement. + Expr *E = nullptr; + /// UE Helper expression of the form: + /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or + /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. + Expr *UE = nullptr; + /// 'd' part of the associated expression/statement. + Expr *D = nullptr; + /// Conditional expression in `atomic compare` construct. + Expr *Cond = nullptr; + /// True if UE has the first form and false if the second. + bool IsXLHSInRHSPart; + /// True if original value of 'x' must be stored in 'v', not an updated one. + bool IsPostfixUpdate; + /// True if 'v' is updated only when the condition is false (compare capture + /// only). + bool IsFailOnly; + }; + /// Creates directive with a list of \a Clauses and 'x', 'v' and 'expr' /// parts of the atomic construct (see Section 2.12.6, atomic Construct, for /// detailed description of 'x', 'v' and 'expr'). @@ -2815,20 +3069,12 @@ public: /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. - /// \param X 'x' part of the associated expression/statement. - /// \param V 'v' part of the associated expression/statement. - /// \param E 'expr' part of the associated expression/statement. - /// \param UE Helper expression of the form - /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or - /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. - /// \param IsXLHSInRHSPart true if \a UE has the first form and false if the - /// second. - /// \param IsPostfixUpdate true if original value of 'x' must be stored in - /// 'v', not an updated one. - static OMPAtomicDirective * - Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, - Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate); + /// \param Exprs Associated expressions or statements. + static OMPAtomicDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, Expressions Exprs); /// Creates an empty directive with the place for \a NumClauses /// clauses. @@ -2840,33 +3086,67 @@ public: unsigned NumClauses, EmptyShell); /// Get 'x' part of the associated expression/statement. - Expr *getX() { return cast_or_null<Expr>(Data->getChildren()[0]); } + Expr *getX() { + return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_X]); + } const Expr *getX() const { - return cast_or_null<Expr>(Data->getChildren()[0]); + return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_X]); } /// Get helper expression of the form /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. - Expr *getUpdateExpr() { return cast_or_null<Expr>(Data->getChildren()[1]); } + Expr *getUpdateExpr() { + return cast_or_null<Expr>( + Data->getChildren()[DataPositionTy::POS_UpdateExpr]); + } const Expr *getUpdateExpr() const { - return cast_or_null<Expr>(Data->getChildren()[1]); + return cast_or_null<Expr>( + Data->getChildren()[DataPositionTy::POS_UpdateExpr]); } /// Return true if helper update expression has form /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. - bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; } + bool isXLHSInRHSPart() const { return Flags.IsXLHSInRHSPart; } /// Return true if 'v' expression must be updated to original value of /// 'x', false if 'v' must be updated to the new value of 'x'. - bool isPostfixUpdate() const { return IsPostfixUpdate; } + bool isPostfixUpdate() const { return Flags.IsPostfixUpdate; } + /// Return true if 'v' is updated only when the condition is evaluated false + /// (compare capture only). + bool isFailOnly() const { return Flags.IsFailOnly; } /// Get 'v' part of the associated expression/statement. - Expr *getV() { return cast_or_null<Expr>(Data->getChildren()[2]); } + Expr *getV() { + return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_V]); + } const Expr *getV() const { - return cast_or_null<Expr>(Data->getChildren()[2]); + return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_V]); + } + /// Get 'r' part of the associated expression/statement. + Expr *getR() { + return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_R]); + } + const Expr *getR() const { + return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_R]); } /// Get 'expr' part of the associated expression/statement. - Expr *getExpr() { return cast_or_null<Expr>(Data->getChildren()[3]); } + Expr *getExpr() { + return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_E]); + } const Expr *getExpr() const { - return cast_or_null<Expr>(Data->getChildren()[3]); + return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_E]); + } + /// Get 'd' part of the associated expression/statement. + Expr *getD() { + return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]); + } + Expr *getD() const { + return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]); + } + /// Get the 'cond' part of the source atomic expression. + Expr *getCondExpr() { + return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]); + } + Expr *getCondExpr() const { + return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]); } static bool classof(const Stmt *T) { @@ -3651,6 +3931,82 @@ public: } }; +/// This represents '#pragma omp masked taskloop' directive. +/// +/// \code +/// #pragma omp masked taskloop private(a,b) grainsize(val) num_tasks(num) +/// \endcode +/// In this example directive '#pragma omp masked taskloop' has clauses +/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val' +/// and 'num_tasks' with expression 'num'. +/// +class OMPMaskedTaskLoopDirective final : public OMPLoopDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + /// true if the construct has inner cancel directive. + bool HasCancel = false; + + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// + OMPMaskedTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum) + : OMPLoopDirective(OMPMaskedTaskLoopDirectiveClass, + llvm::omp::OMPD_masked_taskloop, StartLoc, EndLoc, + CollapsedNum) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// + explicit OMPMaskedTaskLoopDirective(unsigned CollapsedNum) + : OMPLoopDirective(OMPMaskedTaskLoopDirectiveClass, + llvm::omp::OMPD_masked_taskloop, SourceLocation(), + SourceLocation(), CollapsedNum) {} + + /// Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } + +public: + /// Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// \param HasCancel true if this directive has inner cancel directive. + /// + static OMPMaskedTaskLoopDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); + + /// Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPMaskedTaskLoopDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + /// Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPMaskedTaskLoopDirectiveClass; + } +}; + /// This represents '#pragma omp master taskloop simd' directive. /// /// \code @@ -3716,6 +4072,71 @@ public: } }; +/// This represents '#pragma omp masked taskloop simd' directive. +/// +/// \code +/// #pragma omp masked taskloop simd private(a,b) grainsize(val) num_tasks(num) +/// \endcode +/// In this example directive '#pragma omp masked taskloop simd' has clauses +/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val' +/// and 'num_tasks' with expression 'num'. +/// +class OMPMaskedTaskLoopSimdDirective final : public OMPLoopDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// + OMPMaskedTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum) + : OMPLoopDirective(OMPMaskedTaskLoopSimdDirectiveClass, + llvm::omp::OMPD_masked_taskloop_simd, StartLoc, EndLoc, + CollapsedNum) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// + explicit OMPMaskedTaskLoopSimdDirective(unsigned CollapsedNum) + : OMPLoopDirective(OMPMaskedTaskLoopSimdDirectiveClass, + llvm::omp::OMPD_masked_taskloop_simd, SourceLocation(), + SourceLocation(), CollapsedNum) {} + +public: + /// Creates directive with a list of \p Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPMaskedTaskLoopSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with the place for \p NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPMaskedTaskLoopSimdDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPMaskedTaskLoopSimdDirectiveClass; + } +}; + /// This represents '#pragma omp parallel master taskloop' directive. /// /// \code @@ -3794,6 +4215,84 @@ public: } }; +/// This represents '#pragma omp parallel masked taskloop' directive. +/// +/// \code +/// #pragma omp parallel masked taskloop private(a,b) grainsize(val) +/// num_tasks(num) +/// \endcode +/// In this example directive '#pragma omp parallel masked taskloop' has clauses +/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val' +/// and 'num_tasks' with expression 'num'. +/// +class OMPParallelMaskedTaskLoopDirective final : public OMPLoopDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + /// true if the construct has inner cancel directive. + bool HasCancel = false; + + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// + OMPParallelMaskedTaskLoopDirective(SourceLocation StartLoc, + SourceLocation EndLoc, + unsigned CollapsedNum) + : OMPLoopDirective(OMPParallelMaskedTaskLoopDirectiveClass, + llvm::omp::OMPD_parallel_masked_taskloop, StartLoc, + EndLoc, CollapsedNum) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// + explicit OMPParallelMaskedTaskLoopDirective(unsigned CollapsedNum) + : OMPLoopDirective(OMPParallelMaskedTaskLoopDirectiveClass, + llvm::omp::OMPD_parallel_masked_taskloop, + SourceLocation(), SourceLocation(), CollapsedNum) {} + + /// Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } + +public: + /// Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// \param HasCancel true if this directive has inner cancel directive. + /// + static OMPParallelMaskedTaskLoopDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); + + /// Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPParallelMaskedTaskLoopDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + /// Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPParallelMaskedTaskLoopDirectiveClass; + } +}; + /// This represents '#pragma omp parallel master taskloop simd' directive. /// /// \code @@ -3861,6 +4360,73 @@ public: } }; +/// This represents '#pragma omp parallel masked taskloop simd' directive. +/// +/// \code +/// #pragma omp parallel masked taskloop simd private(a,b) grainsize(val) +/// num_tasks(num) +/// \endcode +/// In this example directive '#pragma omp parallel masked taskloop simd' has +/// clauses 'private' with the variables 'a' and 'b', 'grainsize' with +/// expression 'val' and 'num_tasks' with expression 'num'. +/// +class OMPParallelMaskedTaskLoopSimdDirective final : public OMPLoopDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// + OMPParallelMaskedTaskLoopSimdDirective(SourceLocation StartLoc, + SourceLocation EndLoc, + unsigned CollapsedNum) + : OMPLoopDirective(OMPParallelMaskedTaskLoopSimdDirectiveClass, + llvm::omp::OMPD_parallel_masked_taskloop_simd, + StartLoc, EndLoc, CollapsedNum) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// + explicit OMPParallelMaskedTaskLoopSimdDirective(unsigned CollapsedNum) + : OMPLoopDirective(OMPParallelMaskedTaskLoopSimdDirectiveClass, + llvm::omp::OMPD_parallel_masked_taskloop_simd, + SourceLocation(), SourceLocation(), CollapsedNum) {} + +public: + /// Creates directive with a list of \p Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPParallelMaskedTaskLoopSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPParallelMaskedTaskLoopSimdDirective * + CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPParallelMaskedTaskLoopSimdDirectiveClass; + } +}; + /// This represents '#pragma omp distribute' directive. /// /// \code @@ -3908,7 +4474,8 @@ public: static OMPDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs); + Stmt *AssociatedStmt, const HelperExprs &Exprs, + OpenMPDirectiveKind ParamPrevMappedDirective); /// Creates an empty directive with the place /// for \a NumClauses clauses. @@ -4992,7 +5559,7 @@ public: }; /// This represents the '#pragma omp tile' loop transformation directive. -class OMPTileDirective final : public OMPLoopBasedDirective { +class OMPTileDirective final : public OMPLoopTransformationDirective { friend class ASTStmtReader; friend class OMPExecutableDirective; @@ -5004,8 +5571,11 @@ class OMPTileDirective final : public OMPLoopBasedDirective { explicit OMPTileDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned NumLoops) - : OMPLoopBasedDirective(OMPTileDirectiveClass, llvm::omp::OMPD_tile, - StartLoc, EndLoc, NumLoops) {} + : OMPLoopTransformationDirective(OMPTileDirectiveClass, + llvm::omp::OMPD_tile, StartLoc, EndLoc, + NumLoops) { + setNumGeneratedLoops(3 * NumLoops); + } void setPreInits(Stmt *PreInits) { Data->getChildren()[PreInitsOffset] = PreInits; @@ -5042,8 +5612,6 @@ public: static OMPTileDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned NumLoops); - unsigned getNumAssociatedLoops() const { return getLoopsNumber(); } - /// Gets/sets the associated loops after tiling. /// /// This is in de-sugared format stored as a CompoundStmt. @@ -5073,7 +5641,7 @@ public: /// #pragma omp unroll /// for (int i = 0; i < 64; ++i) /// \endcode -class OMPUnrollDirective final : public OMPLoopBasedDirective { +class OMPUnrollDirective final : public OMPLoopTransformationDirective { friend class ASTStmtReader; friend class OMPExecutableDirective; @@ -5084,8 +5652,9 @@ class OMPUnrollDirective final : public OMPLoopBasedDirective { }; explicit OMPUnrollDirective(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPLoopBasedDirective(OMPUnrollDirectiveClass, llvm::omp::OMPD_unroll, - StartLoc, EndLoc, 1) {} + : OMPLoopTransformationDirective(OMPUnrollDirectiveClass, + llvm::omp::OMPD_unroll, StartLoc, EndLoc, + 1) {} /// Set the pre-init statements. void setPreInits(Stmt *PreInits) { @@ -5111,7 +5680,7 @@ public: static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, - Stmt *TransformedStmt, Stmt *PreInits); + unsigned NumGeneratedLoops, Stmt *TransformedStmt, Stmt *PreInits); /// Build an empty '#pragma omp unroll' AST node for deserialization. /// @@ -5360,6 +5929,412 @@ public: } }; +/// This represents '#pragma omp metadirective' directive. +/// +/// \code +/// #pragma omp metadirective when(user={condition(N>10)}: parallel for) +/// \endcode +/// In this example directive '#pragma omp metadirective' has clauses 'when' +/// with a dynamic user condition to check if a variable 'N > 10' +/// +class OMPMetaDirective final : public OMPExecutableDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + Stmt *IfStmt; + + OMPMetaDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(OMPMetaDirectiveClass, + llvm::omp::OMPD_metadirective, StartLoc, + EndLoc) {} + explicit OMPMetaDirective() + : OMPExecutableDirective(OMPMetaDirectiveClass, + llvm::omp::OMPD_metadirective, SourceLocation(), + SourceLocation()) {} + + void setIfStmt(Stmt *S) { IfStmt = S; } + +public: + static OMPMetaDirective *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, Stmt *IfStmt); + static OMPMetaDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, + EmptyShell); + Stmt *getIfStmt() const { return IfStmt; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPMetaDirectiveClass; + } +}; + +/// This represents '#pragma omp loop' directive. +/// +/// \code +/// #pragma omp loop private(a,b) binding(parallel) order(concurrent) +/// \endcode +/// In this example directive '#pragma omp loop' has +/// clauses 'private' with the variables 'a' and 'b', 'binding' with +/// modifier 'parallel' and 'order(concurrent). +/// +class OMPGenericLoopDirective final : public OMPLoopDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// + OMPGenericLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum) + : OMPLoopDirective(OMPGenericLoopDirectiveClass, llvm::omp::OMPD_loop, + StartLoc, EndLoc, CollapsedNum) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// + explicit OMPGenericLoopDirective(unsigned CollapsedNum) + : OMPLoopDirective(OMPGenericLoopDirectiveClass, llvm::omp::OMPD_loop, + SourceLocation(), SourceLocation(), CollapsedNum) {} + +public: + /// Creates directive with a list of \p Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPGenericLoopDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with a place for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// \param CollapsedNum Number of collapsed nested loops. + /// + static OMPGenericLoopDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPGenericLoopDirectiveClass; + } +}; + +/// This represents '#pragma omp teams loop' directive. +/// +/// \code +/// #pragma omp teams loop private(a,b) order(concurrent) +/// \endcode +/// In this example directive '#pragma omp teams loop' has +/// clauses 'private' with the variables 'a' and 'b', and order(concurrent). +/// +class OMPTeamsGenericLoopDirective final : public OMPLoopDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// + OMPTeamsGenericLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum) + : OMPLoopDirective(OMPTeamsGenericLoopDirectiveClass, + llvm::omp::OMPD_teams_loop, StartLoc, EndLoc, + CollapsedNum) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// + explicit OMPTeamsGenericLoopDirective(unsigned CollapsedNum) + : OMPLoopDirective(OMPTeamsGenericLoopDirectiveClass, + llvm::omp::OMPD_teams_loop, SourceLocation(), + SourceLocation(), CollapsedNum) {} + +public: + /// Creates directive with a list of \p Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPTeamsGenericLoopDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPTeamsGenericLoopDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTeamsGenericLoopDirectiveClass; + } +}; + +/// This represents '#pragma omp target teams loop' directive. +/// +/// \code +/// #pragma omp target teams loop private(a,b) order(concurrent) +/// \endcode +/// In this example directive '#pragma omp target teams loop' has +/// clauses 'private' with the variables 'a' and 'b', and order(concurrent). +/// +class OMPTargetTeamsGenericLoopDirective final : public OMPLoopDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// + OMPTargetTeamsGenericLoopDirective(SourceLocation StartLoc, + SourceLocation EndLoc, + unsigned CollapsedNum) + : OMPLoopDirective(OMPTargetTeamsGenericLoopDirectiveClass, + llvm::omp::OMPD_target_teams_loop, StartLoc, EndLoc, + CollapsedNum) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// + explicit OMPTargetTeamsGenericLoopDirective(unsigned CollapsedNum) + : OMPLoopDirective(OMPTargetTeamsGenericLoopDirectiveClass, + llvm::omp::OMPD_target_teams_loop, SourceLocation(), + SourceLocation(), CollapsedNum) {} + +public: + /// Creates directive with a list of \p Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPTargetTeamsGenericLoopDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPTargetTeamsGenericLoopDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetTeamsGenericLoopDirectiveClass; + } +}; + +/// This represents '#pragma omp parallel loop' directive. +/// +/// \code +/// #pragma omp parallel loop private(a,b) order(concurrent) +/// \endcode +/// In this example directive '#pragma omp parallel loop' has +/// clauses 'private' with the variables 'a' and 'b', and order(concurrent). +/// +class OMPParallelGenericLoopDirective final : public OMPLoopDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// + OMPParallelGenericLoopDirective(SourceLocation StartLoc, + SourceLocation EndLoc, unsigned CollapsedNum) + : OMPLoopDirective(OMPParallelGenericLoopDirectiveClass, + llvm::omp::OMPD_parallel_loop, StartLoc, EndLoc, + CollapsedNum) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// + explicit OMPParallelGenericLoopDirective(unsigned CollapsedNum) + : OMPLoopDirective(OMPParallelGenericLoopDirectiveClass, + llvm::omp::OMPD_parallel_loop, SourceLocation(), + SourceLocation(), CollapsedNum) {} + +public: + /// Creates directive with a list of \p Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPParallelGenericLoopDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPParallelGenericLoopDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPParallelGenericLoopDirectiveClass; + } +}; + +/// This represents '#pragma omp target parallel loop' directive. +/// +/// \code +/// #pragma omp target parallel loop private(a,b) order(concurrent) +/// \endcode +/// In this example directive '#pragma omp target parallel loop' has +/// clauses 'private' with the variables 'a' and 'b', and order(concurrent). +/// +class OMPTargetParallelGenericLoopDirective final : public OMPLoopDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// + OMPTargetParallelGenericLoopDirective(SourceLocation StartLoc, + SourceLocation EndLoc, + unsigned CollapsedNum) + : OMPLoopDirective(OMPTargetParallelGenericLoopDirectiveClass, + llvm::omp::OMPD_target_parallel_loop, StartLoc, EndLoc, + CollapsedNum) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// + explicit OMPTargetParallelGenericLoopDirective(unsigned CollapsedNum) + : OMPLoopDirective(OMPTargetParallelGenericLoopDirectiveClass, + llvm::omp::OMPD_target_parallel_loop, SourceLocation(), + SourceLocation(), CollapsedNum) {} + +public: + /// Creates directive with a list of \p Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPTargetParallelGenericLoopDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPTargetParallelGenericLoopDirective * + CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass; + } +}; + +/// This represents '#pragma omp error' directive. +/// +/// \code +/// #pragma omp error +/// \endcode +class OMPErrorDirective final : public OMPExecutableDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPErrorDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error, + StartLoc, EndLoc) {} + /// Build an empty directive. + /// + explicit OMPErrorDirective() + : OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error, + SourceLocation(), SourceLocation()) {} + +public: + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// + static OMPErrorDirective *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses); + + /// Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPErrorDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPErrorDirectiveClass; + } +}; } // end namespace clang #endif diff --git a/contrib/llvm-project/clang/include/clang/AST/TemplateArgumentVisitor.h b/contrib/llvm-project/clang/include/clang/AST/TemplateArgumentVisitor.h index 190aa97adf45..cf0d32201580 100644 --- a/contrib/llvm-project/clang/include/clang/AST/TemplateArgumentVisitor.h +++ b/contrib/llvm-project/clang/include/clang/AST/TemplateArgumentVisitor.h @@ -37,6 +37,7 @@ public: DISPATCH(Declaration); DISPATCH(NullPtr); DISPATCH(Integral); + DISPATCH(StructuralValue); DISPATCH(Template); DISPATCH(TemplateExpansion); DISPATCH(Expression); @@ -59,6 +60,7 @@ public: VISIT_METHOD(Declaration); VISIT_METHOD(NullPtr); VISIT_METHOD(Integral); + VISIT_METHOD(StructuralValue); VISIT_METHOD(Template); VISIT_METHOD(TemplateExpansion); VISIT_METHOD(Expression); diff --git a/contrib/llvm-project/clang/include/clang/AST/TemplateBase.h b/contrib/llvm-project/clang/include/clang/AST/TemplateBase.h index fa27a12cfbb9..fea2c8ccfee6 100644 --- a/contrib/llvm-project/clang/include/clang/AST/TemplateBase.h +++ b/contrib/llvm-project/clang/include/clang/AST/TemplateBase.h @@ -23,14 +23,13 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/TrailingObjects.h" #include <cassert> #include <cstddef> #include <cstdint> +#include <optional> namespace llvm { @@ -51,8 +50,8 @@ template <> struct PointerLikeTypeTraits<clang::Expr *> { namespace clang { +class APValue; class ASTContext; -class DiagnosticBuilder; class Expr; struct PrintingPolicy; class TypeSourceInfo; @@ -82,6 +81,13 @@ public: /// that was provided for an integral non-type template parameter. Integral, + /// The template argument is a non-type template argument that can't be + /// represented by the special-case Declaration, NullPtr, or Integral + /// forms. These values are only ever produced by constant evaluation, + /// so cannot be dependent. + /// TODO: merge Declaration, NullPtr and Integral into this? + StructuralValue, + /// The template argument is a template name that was provided for a /// template template parameter. Template, @@ -105,16 +111,23 @@ private: /// The kind of template argument we're storing. struct DA { - unsigned Kind; + LLVM_PREFERRED_TYPE(ArgKind) + unsigned Kind : 31; + LLVM_PREFERRED_TYPE(bool) + unsigned IsDefaulted : 1; void *QT; ValueDecl *D; }; struct I { - unsigned Kind; + LLVM_PREFERRED_TYPE(ArgKind) + unsigned Kind : 31; + LLVM_PREFERRED_TYPE(bool) + unsigned IsDefaulted : 1; // We store a decomposed APSInt with the data allocated by ASTContext if // BitWidth > 64. The memory may be shared between multiple // TemplateArgument instances. unsigned BitWidth : 31; + LLVM_PREFERRED_TYPE(bool) unsigned IsUnsigned : 1; union { /// Used to store the <= 64 bits integer value. @@ -125,51 +138,77 @@ private: }; void *Type; }; + struct V { + LLVM_PREFERRED_TYPE(ArgKind) + unsigned Kind : 31; + LLVM_PREFERRED_TYPE(bool) + unsigned IsDefaulted : 1; + APValue *Value; + void *Type; + }; struct A { - unsigned Kind; + LLVM_PREFERRED_TYPE(ArgKind) + unsigned Kind : 31; + LLVM_PREFERRED_TYPE(bool) + unsigned IsDefaulted : 1; unsigned NumArgs; const TemplateArgument *Args; }; struct TA { - unsigned Kind; + LLVM_PREFERRED_TYPE(ArgKind) + unsigned Kind : 31; + LLVM_PREFERRED_TYPE(bool) + unsigned IsDefaulted : 1; unsigned NumExpansions; void *Name; }; struct TV { - unsigned Kind; + LLVM_PREFERRED_TYPE(ArgKind) + unsigned Kind : 31; + LLVM_PREFERRED_TYPE(bool) + unsigned IsDefaulted : 1; uintptr_t V; }; union { struct DA DeclArg; struct I Integer; + struct V Value; struct A Args; struct TA TemplateArg; struct TV TypeOrValue; }; + void initFromType(QualType T, bool IsNullPtr, bool IsDefaulted); + void initFromDeclaration(ValueDecl *D, QualType QT, bool IsDefaulted); + void initFromIntegral(const ASTContext &Ctx, const llvm::APSInt &Value, + QualType Type, bool IsDefaulted); + void initFromStructural(const ASTContext &Ctx, QualType Type, + const APValue &V, bool IsDefaulted); + public: /// Construct an empty, invalid template argument. - constexpr TemplateArgument() : TypeOrValue({Null, 0}) {} + constexpr TemplateArgument() : TypeOrValue({Null, 0, /* IsDefaulted */ 0}) {} /// Construct a template type argument. - TemplateArgument(QualType T, bool isNullPtr = false) { - TypeOrValue.Kind = isNullPtr ? NullPtr : Type; - TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); + TemplateArgument(QualType T, bool isNullPtr = false, + bool IsDefaulted = false) { + initFromType(T, isNullPtr, IsDefaulted); } - /// Construct a template argument that refers to a - /// declaration, which is either an external declaration or a - /// template declaration. - TemplateArgument(ValueDecl *D, QualType QT) { - assert(D && "Expected decl"); - DeclArg.Kind = Declaration; - DeclArg.QT = QT.getAsOpaquePtr(); - DeclArg.D = D; + /// Construct a template argument that refers to a (non-dependent) + /// declaration. + TemplateArgument(ValueDecl *D, QualType QT, bool IsDefaulted = false) { + initFromDeclaration(D, QT, IsDefaulted); } /// Construct an integral constant template argument. The memory to /// store the value is allocated with Ctx. - TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type); + TemplateArgument(const ASTContext &Ctx, const llvm::APSInt &Value, + QualType Type, bool IsDefaulted = false); + + /// Construct a template argument from an arbitrary constant value. + TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value, + bool IsDefaulted = false); /// Construct an integral constant template argument with the same /// value as Other but a different type. @@ -186,8 +225,12 @@ public: /// is taken. /// /// \param Name The template name. - TemplateArgument(TemplateName Name) { + /// + /// \param IsDefaulted If 'true', implies that this TemplateArgument + /// corresponds to a default template parameter + TemplateArgument(TemplateName Name, bool IsDefaulted = false) { TemplateArg.Kind = Template; + TemplateArg.IsDefaulted = IsDefaulted; TemplateArg.Name = Name.getAsVoidPointer(); TemplateArg.NumExpansions = 0; } @@ -203,8 +246,13 @@ public: /// /// \param NumExpansions The number of expansions that will be generated by /// instantiating - TemplateArgument(TemplateName Name, Optional<unsigned> NumExpansions) { + /// + /// \param IsDefaulted If 'true', implies that this TemplateArgument + /// corresponds to a default template parameter + TemplateArgument(TemplateName Name, std::optional<unsigned> NumExpansions, + bool IsDefaulted = false) { TemplateArg.Kind = TemplateExpansion; + TemplateArg.IsDefaulted = IsDefaulted; TemplateArg.Name = Name.getAsVoidPointer(); if (NumExpansions) TemplateArg.NumExpansions = *NumExpansions + 1; @@ -217,8 +265,9 @@ public: /// This form of template argument only occurs in template argument /// lists used for dependent types and for expression; it will not /// occur in a non-dependent, canonical template argument list. - TemplateArgument(Expr *E) { + TemplateArgument(Expr *E, bool IsDefaulted = false) { TypeOrValue.Kind = Expression; + TypeOrValue.IsDefaulted = IsDefaulted; TypeOrValue.V = reinterpret_cast<uintptr_t>(E); } @@ -228,13 +277,14 @@ public: /// outlives the TemplateArgument itself. explicit TemplateArgument(ArrayRef<TemplateArgument> Args) { this->Args.Kind = Pack; + this->Args.IsDefaulted = false; this->Args.Args = Args.data(); this->Args.NumArgs = Args.size(); } - TemplateArgument(TemplateName, bool) = delete; - - static TemplateArgument getEmptyPack() { return TemplateArgument(None); } + static TemplateArgument getEmptyPack() { + return TemplateArgument(std::nullopt); + } /// Create a new template argument pack by copying the given set of /// template arguments. @@ -268,7 +318,7 @@ public: /// Retrieve the type for a type template argument. QualType getAsType() const { assert(getKind() == Type && "Unexpected kind"); - return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); + return QualType::getFromOpaquePtr(reinterpret_cast<void *>(TypeOrValue.V)); } /// Retrieve the declaration for a declaration non-type @@ -286,7 +336,7 @@ public: /// Retrieve the type for null non-type template argument. QualType getNullPtrType() const { assert(getKind() == NullPtr && "Unexpected kind"); - return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); + return QualType::getFromOpaquePtr(reinterpret_cast<void *>(TypeOrValue.V)); } /// Retrieve the template name for a template name argument. @@ -306,7 +356,7 @@ public: /// Retrieve the number of expansions that a template template argument /// expansion will produce, if known. - Optional<unsigned> getNumTemplateExpansions() const; + std::optional<unsigned> getNumTemplateExpansions() const; /// Retrieve the template argument as an integral value. // FIXME: Provide a way to read the integral data without copying the value. @@ -319,7 +369,7 @@ public: return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned); unsigned NumWords = APInt::getNumWords(Integer.BitWidth); - return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)), + return APSInt(APInt(Integer.BitWidth, ArrayRef(Integer.pVal, NumWords)), Integer.IsUnsigned); } @@ -334,6 +384,22 @@ public: Integer.Type = T.getAsOpaquePtr(); } + /// Set to 'true' if this TemplateArgument corresponds to a + /// default template parameter. + void setIsDefaulted(bool v) { TypeOrValue.IsDefaulted = v; } + + /// If returns 'true', this TemplateArgument corresponds to a + /// default template parameter. + bool getIsDefaulted() const { return (bool)TypeOrValue.IsDefaulted; } + + /// Get the value of a StructuralValue. + const APValue &getAsStructuralValue() const { return *Value.Value; } + + /// Get the type of a StructuralValue. + QualType getStructuralValueType() const { + return QualType::getFromOpaquePtr(Value.Type); + } + /// If this is a non-type template argument, get its type. Otherwise, /// returns a null QualType. QualType getNonTypeTemplateArgumentType() const; @@ -364,7 +430,7 @@ public: /// Iterator range referencing all of the elements of a template /// argument pack. ArrayRef<TemplateArgument> pack_elements() const { - return llvm::makeArrayRef(pack_begin(), pack_end()); + return llvm::ArrayRef(pack_begin(), pack_end()); } /// The number of template arguments in the given template argument @@ -377,7 +443,7 @@ public: /// Return the array of arguments in this template argument pack. ArrayRef<TemplateArgument> getPackAsArray() const { assert(getKind() == Pack); - return llvm::makeArrayRef(Args.Args, Args.NumArgs); + return llvm::ArrayRef(Args.Args, Args.NumArgs); } /// Determines whether two template arguments are superficially the @@ -479,6 +545,7 @@ public: assert(Argument.getKind() == TemplateArgument::NullPtr || Argument.getKind() == TemplateArgument::Integral || Argument.getKind() == TemplateArgument::Declaration || + Argument.getKind() == TemplateArgument::StructuralValue || Argument.getKind() == TemplateArgument::Expression); } @@ -504,13 +571,9 @@ public: /// - Fetches the full source range of the argument. SourceRange getSourceRange() const LLVM_READONLY; - const TemplateArgument &getArgument() const { - return Argument; - } + const TemplateArgument &getArgument() const { return Argument; } - TemplateArgumentLocInfo getLocInfo() const { - return LocInfo; - } + TemplateArgumentLocInfo getLocInfo() const { return LocInfo; } TypeSourceInfo *getTypeSourceInfo() const { if (Argument.getKind() != TemplateArgument::Type) @@ -538,6 +601,11 @@ public: return LocInfo.getAsExpr(); } + Expr *getSourceStructuralValueExpression() const { + assert(Argument.getKind() == TemplateArgument::StructuralValue); + return LocInfo.getAsExpr(); + } + NestedNameSpecifierLoc getTemplateQualifierLoc() const { if (Argument.getKind() != TemplateArgument::Template && Argument.getKind() != TemplateArgument::TemplateExpansion) @@ -569,8 +637,7 @@ class TemplateArgumentListInfo { public: TemplateArgumentListInfo() = default; - TemplateArgumentListInfo(SourceLocation LAngleLoc, - SourceLocation RAngleLoc) + TemplateArgumentListInfo(SourceLocation LAngleLoc, SourceLocation RAngleLoc) : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} // This can leak if used in an AST node, use ASTTemplateArgumentListInfo @@ -589,21 +656,15 @@ public: return Arguments.data(); } - llvm::ArrayRef<TemplateArgumentLoc> arguments() const { - return Arguments; - } + llvm::ArrayRef<TemplateArgumentLoc> arguments() const { return Arguments; } const TemplateArgumentLoc &operator[](unsigned I) const { return Arguments[I]; } - TemplateArgumentLoc &operator[](unsigned I) { - return Arguments[I]; - } + TemplateArgumentLoc &operator[](unsigned I) { return Arguments[I]; } - void addArgument(const TemplateArgumentLoc &Loc) { - Arguments.push_back(Loc); - } + void addArgument(const TemplateArgumentLoc &Loc) { Arguments.push_back(Loc); } }; /// Represents an explicit template argument list in C++, e.g., @@ -619,6 +680,9 @@ private: ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List); + // FIXME: Is it ever necessary to copy to another context? + ASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *List); + public: /// The source location of the left angle bracket ('<'). SourceLocation LAngleLoc; @@ -639,7 +703,7 @@ public: unsigned getNumTemplateArgs() const { return NumTemplateArgs; } llvm::ArrayRef<TemplateArgumentLoc> arguments() const { - return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs()); + return llvm::ArrayRef(getTemplateArgs(), getNumTemplateArgs()); } const TemplateArgumentLoc &operator[](unsigned I) const { @@ -648,6 +712,10 @@ public: static const ASTTemplateArgumentListInfo * Create(const ASTContext &C, const TemplateArgumentListInfo &List); + + // FIXME: Is it ever necessary to copy to another context? + static const ASTTemplateArgumentListInfo * + Create(const ASTContext &C, const ASTTemplateArgumentListInfo *List); }; /// Represents an explicit template argument list in C++, e.g., @@ -692,33 +760,6 @@ struct alignas(void *) ASTTemplateKWAndArgsInfo { const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, const TemplateArgument &Arg); -inline TemplateSpecializationType::iterator - TemplateSpecializationType::end() const { - return getArgs() + getNumArgs(); -} - -inline DependentTemplateSpecializationType::iterator - DependentTemplateSpecializationType::end() const { - return getArgs() + getNumArgs(); -} - -inline const TemplateArgument & - TemplateSpecializationType::getArg(unsigned Idx) const { - assert(Idx < getNumArgs() && "Template argument out of range"); - return getArgs()[Idx]; -} - -inline const TemplateArgument & - DependentTemplateSpecializationType::getArg(unsigned Idx) const { - assert(Idx < getNumArgs() && "Template argument out of range"); - return getArgs()[Idx]; -} - -inline const TemplateArgument &AutoType::getArg(unsigned Idx) const { - assert(Idx < getNumArgs() && "Template argument out of range"); - return getArgs()[Idx]; -} - } // namespace clang #endif // LLVM_CLANG_AST_TEMPLATEBASE_H diff --git a/contrib/llvm-project/clang/include/clang/AST/TemplateName.h b/contrib/llvm-project/clang/include/clang/AST/TemplateName.h index 010b813dc525..b7732e54ba10 100644 --- a/contrib/llvm-project/clang/include/clang/AST/TemplateName.h +++ b/contrib/llvm-project/clang/include/clang/AST/TemplateName.h @@ -21,19 +21,19 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include <cassert> +#include <optional> namespace clang { class ASTContext; +class Decl; class DependentTemplateName; -class DiagnosticBuilder; class IdentifierInfo; class NamedDecl; class NestedNameSpecifier; enum OverloadedOperatorKind : int; class OverloadedTemplateStorage; class AssumedTemplateStorage; -class PartialDiagnostic; struct PrintingPolicy; class QualifiedTemplateName; class SubstTemplateTemplateParmPackStorage; @@ -41,6 +41,7 @@ class SubstTemplateTemplateParmStorage; class TemplateArgument; class TemplateDecl; class TemplateTemplateParmDecl; +class UsingShadowDecl; /// Implementation class used to describe either a set of overloaded /// template names or an already-substituted template template parameter pack. @@ -54,12 +55,15 @@ protected: }; struct BitsTag { - /// A Kind. + LLVM_PREFERRED_TYPE(Kind) unsigned Kind : 2; - /// The number of stored templates or template arguments, - /// depending on which subclass we have. - unsigned Size : 30; + // The template parameter index. + unsigned Index : 15; + + /// The pack index, or the number of stored templates + /// or template arguments, depending on which subclass we have. + unsigned Data : 15; }; union { @@ -67,14 +71,13 @@ protected: void *PointerAlignment; }; - UncommonTemplateNameStorage(Kind kind, unsigned size) { - Bits.Kind = kind; - Bits.Size = size; + UncommonTemplateNameStorage(Kind Kind, unsigned Index, unsigned Data) { + Bits.Kind = Kind; + Bits.Index = Index; + Bits.Data = Data; } public: - unsigned size() const { return Bits.Size; } - OverloadedTemplateStorage *getAsOverloadedStorage() { return Bits.Kind == Overloaded ? reinterpret_cast<OverloadedTemplateStorage *>(this) @@ -106,7 +109,7 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage { friend class ASTContext; OverloadedTemplateStorage(unsigned size) - : UncommonTemplateNameStorage(Overloaded, size) {} + : UncommonTemplateNameStorage(Overloaded, 0, size) {} NamedDecl **getStorage() { return reinterpret_cast<NamedDecl **>(this + 1); @@ -116,13 +119,15 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage { } public: + unsigned size() const { return Bits.Data; } + using iterator = NamedDecl *const *; iterator begin() const { return getStorage(); } - iterator end() const { return getStorage() + size(); } + iterator end() const { return getStorage() + Bits.Data; } llvm::ArrayRef<NamedDecl*> decls() const { - return llvm::makeArrayRef(begin(), end()); + return llvm::ArrayRef(begin(), end()); } }; @@ -132,23 +137,29 @@ public: /// This kind of template names occurs when the parameter pack has been /// provided with a template template argument pack in a context where its /// enclosing pack expansion could not be fully expanded. -class SubstTemplateTemplateParmPackStorage - : public UncommonTemplateNameStorage, public llvm::FoldingSetNode -{ - TemplateTemplateParmDecl *Parameter; +class SubstTemplateTemplateParmPackStorage : public UncommonTemplateNameStorage, + public llvm::FoldingSetNode { const TemplateArgument *Arguments; + llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal; public: - SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter, - unsigned Size, - const TemplateArgument *Arguments) - : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size), - Parameter(Parameter), Arguments(Arguments) {} + SubstTemplateTemplateParmPackStorage(ArrayRef<TemplateArgument> ArgPack, + Decl *AssociatedDecl, unsigned Index, + bool Final); + + /// A template-like entity which owns the whole pattern being substituted. + /// This will own a set of template parameters. + Decl *getAssociatedDecl() const; + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getParameterPack()->getIndex()`. + unsigned getIndex() const { return Bits.Index; } + + // When true the substitution will be 'Final' (subst node won't be placed). + bool getFinal() const; /// Retrieve the template template parameter pack being substituted. - TemplateTemplateParmDecl *getParameterPack() const { - return Parameter; - } + TemplateTemplateParmDecl *getParameterPack() const; /// Retrieve the template template argument pack with which this /// parameter was substituted. @@ -156,10 +167,9 @@ public: void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context); - static void Profile(llvm::FoldingSetNodeID &ID, - ASTContext &Context, - TemplateTemplateParmDecl *Parameter, - const TemplateArgument &ArgPack); + static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + const TemplateArgument &ArgPack, Decl *AssociatedDecl, + unsigned Index, bool Final); }; /// Represents a C++ template name within the type system. @@ -190,8 +200,12 @@ public: /// specifier in the typedef. "apply" is a nested template, and can /// only be understood in the context of class TemplateName { + // NameDecl is either a TemplateDecl or a UsingShadowDecl depending on the + // NameKind. + // !! There is no free low bits in 32-bit builds to discriminate more than 4 + // pointer types in PointerUnion. using StorageType = - llvm::PointerUnion<TemplateDecl *, UncommonTemplateNameStorage *, + llvm::PointerUnion<Decl *, UncommonTemplateNameStorage *, QualifiedTemplateName *, DependentTemplateName *>; StorageType Storage; @@ -226,7 +240,11 @@ public: /// A template template parameter pack that has been substituted for /// a template template argument pack, but has not yet been expanded into /// individual arguments. - SubstTemplateTemplateParmPack + SubstTemplateTemplateParmPack, + + /// A template name that refers to a template declaration found through a + /// specific using shadow declaration. + UsingTemplate, }; TemplateName() = default; @@ -237,6 +255,7 @@ public: explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage); explicit TemplateName(QualifiedTemplateName *Qual); explicit TemplateName(DependentTemplateName *Dep); + explicit TemplateName(UsingShadowDecl *Using); /// Determine whether this template name is NULL. bool isNull() const; @@ -289,6 +308,10 @@ public: /// structure, if any. DependentTemplateName *getAsDependentTemplateName() const; + /// Retrieve the using shadow declaration through which the underlying + /// template declaration is introduced, if any. + UsingShadowDecl *getAsUsingShadowDecl() const; + TemplateName getUnderlying() const; /// Get the template name to substitute when this template name is used as a @@ -309,16 +332,17 @@ public: /// unexpanded parameter pack (for C++0x variadic templates). bool containsUnexpandedParameterPack() const; + enum class Qualified { None, AsWritten, Fully }; /// Print the template name. /// /// \param OS the output stream to which the template name will be /// printed. /// - /// \param SuppressNNS if true, don't print the - /// nested-name-specifier that precedes the template name (if it has - /// one). + /// \param Qual print the (Qualified::None) simple name, + /// (Qualified::AsWritten) any written (possibly partial) qualifier, or + /// (Qualified::Fully) the fully qualified name. void print(raw_ostream &OS, const PrintingPolicy &Policy, - bool SuppressNNS = false) const; + Qualified Qual = Qualified::AsWritten) const; /// Debugging aid that dumps the template name. void dump(raw_ostream &OS) const; @@ -327,9 +351,7 @@ public: /// error. void dump() const; - void Profile(llvm::FoldingSetNodeID &ID) { - ID.AddPointer(Storage.getOpaqueValue()); - } + void Profile(llvm::FoldingSetNodeID &ID); /// Retrieve the template name as a void pointer. void *getAsVoidPointer() const { return Storage.getOpaqueValue(); } @@ -351,23 +373,41 @@ class SubstTemplateTemplateParmStorage : public UncommonTemplateNameStorage, public llvm::FoldingSetNode { friend class ASTContext; - TemplateTemplateParmDecl *Parameter; TemplateName Replacement; - - SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter, - TemplateName replacement) - : UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0), - Parameter(parameter), Replacement(replacement) {} + Decl *AssociatedDecl; + + SubstTemplateTemplateParmStorage(TemplateName Replacement, + Decl *AssociatedDecl, unsigned Index, + std::optional<unsigned> PackIndex) + : UncommonTemplateNameStorage(SubstTemplateTemplateParm, Index, + PackIndex ? *PackIndex + 1 : 0), + Replacement(Replacement), AssociatedDecl(AssociatedDecl) { + assert(AssociatedDecl != nullptr); + } public: - TemplateTemplateParmDecl *getParameter() const { return Parameter; } + /// A template-like entity which owns the whole pattern being substituted. + /// This will own a set of template parameters. + Decl *getAssociatedDecl() const { return AssociatedDecl; } + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getParameter()->getIndex()`. + unsigned getIndex() const { return Bits.Index; } + + std::optional<unsigned> getPackIndex() const { + if (Bits.Data == 0) + return std::nullopt; + return Bits.Data - 1; + } + + TemplateTemplateParmDecl *getParameter() const; TemplateName getReplacement() const { return Replacement; } void Profile(llvm::FoldingSetNodeID &ID); - static void Profile(llvm::FoldingSetNodeID &ID, - TemplateTemplateParmDecl *parameter, - TemplateName replacement); + static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Replacement, + Decl *AssociatedDecl, unsigned Index, + std::optional<unsigned> PackIndex); }; inline TemplateName TemplateName::getUnderlying() const { @@ -400,13 +440,19 @@ class QualifiedTemplateName : public llvm::FoldingSetNode { /// this name with DependentTemplateName). llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier; - /// The template declaration or set of overloaded function templates - /// that this qualified name refers to. - TemplateDecl *Template; + /// The underlying template name, it is either + /// 1) a Template -- a template declaration that this qualified name refers + /// to. + /// 2) or a UsingTemplate -- a template declaration introduced by a + /// using-shadow declaration. + TemplateName UnderlyingTemplate; QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, - TemplateDecl *Template) - : Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) {} + TemplateName Template) + : Qualifier(NNS, TemplateKeyword ? 1 : 0), UnderlyingTemplate(Template) { + assert(UnderlyingTemplate.getKind() == TemplateName::Template || + UnderlyingTemplate.getKind() == TemplateName::UsingTemplate); + } public: /// Return the nested name specifier that qualifies this name. @@ -416,23 +462,18 @@ public: /// keyword. bool hasTemplateKeyword() const { return Qualifier.getInt(); } - /// The template declaration that this qualified name refers - /// to. - TemplateDecl *getDecl() const { return Template; } - - /// The template declaration to which this qualified name - /// refers. - TemplateDecl *getTemplateDecl() const { return Template; } + /// Return the underlying template name. + TemplateName getUnderlyingTemplate() const { return UnderlyingTemplate; } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl()); + Profile(ID, getQualifier(), hasTemplateKeyword(), UnderlyingTemplate); } static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, - bool TemplateKeyword, TemplateDecl *Template) { + bool TemplateKeyword, TemplateName TN) { ID.AddPointer(NNS); ID.AddBoolean(TemplateKeyword); - ID.AddPointer(Template); + ID.AddPointer(TN.getAsVoidPointer()); } }; diff --git a/contrib/llvm-project/clang/include/clang/AST/TextNodeDumper.h b/contrib/llvm-project/clang/include/clang/AST/TextNodeDumper.h index 0eb0031de11f..732749ad305e 100644 --- a/contrib/llvm-project/clang/include/clang/AST/TextNodeDumper.h +++ b/contrib/llvm-project/clang/include/clang/AST/TextNodeDumper.h @@ -189,6 +189,8 @@ public: void Visit(const GenericSelectionExpr::ConstAssociation &A); + void Visit(const ConceptReference *); + void Visit(const concepts::Requirement *R); void Visit(const APValue &Value, QualType Ty); @@ -202,6 +204,9 @@ public: void dumpName(const NamedDecl *ND); void dumpAccessSpecifier(AccessSpecifier AS); void dumpCleanupObject(const ExprWithCleanups::CleanupObject &C); + void dumpTemplateSpecializationKind(TemplateSpecializationKind TSK); + void dumpNestedNameSpecifier(const NestedNameSpecifier *NNS); + void dumpConceptReference(const ConceptReference *R); void dumpDeclRef(const Decl *D, StringRef Label = {}); @@ -246,12 +251,17 @@ public: void VisitLabelStmt(const LabelStmt *Node); void VisitGotoStmt(const GotoStmt *Node); void VisitCaseStmt(const CaseStmt *Node); + void VisitReturnStmt(const ReturnStmt *Node); + void VisitCoawaitExpr(const CoawaitExpr *Node); + void VisitCoreturnStmt(const CoreturnStmt *Node); + void VisitCompoundStmt(const CompoundStmt *Node); void VisitConstantExpr(const ConstantExpr *Node); void VisitCallExpr(const CallExpr *Node); void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node); void VisitCastExpr(const CastExpr *Node); void VisitImplicitCastExpr(const ImplicitCastExpr *Node); void VisitDeclRefExpr(const DeclRefExpr *Node); + void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *Node); void VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *Node); void VisitPredefinedExpr(const PredefinedExpr *Node); void VisitCharacterLiteral(const CharacterLiteral *Node); @@ -311,11 +321,17 @@ public: void VisitFunctionType(const FunctionType *T); void VisitFunctionProtoType(const FunctionProtoType *T); void VisitUnresolvedUsingType(const UnresolvedUsingType *T); + void VisitUsingType(const UsingType *T); void VisitTypedefType(const TypedefType *T); void VisitUnaryTransformType(const UnaryTransformType *T); void VisitTagType(const TagType *T); void VisitTemplateTypeParmType(const TemplateTypeParmType *T); + void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T); + void + VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T); void VisitAutoType(const AutoType *T); + void VisitDeducedTemplateSpecializationType( + const DeducedTemplateSpecializationType *T); void VisitTemplateSpecializationType(const TemplateSpecializationType *T); void VisitInjectedClassNameType(const InjectedClassNameType *T); void VisitObjCInterfaceType(const ObjCInterfaceType *T); @@ -376,6 +392,7 @@ public: void VisitConceptDecl(const ConceptDecl *D); void VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D); + void VisitHLSLBufferDecl(const HLSLBufferDecl *D); }; } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/AST/Type.h b/contrib/llvm-project/clang/include/clang/AST/Type.h index 9f46d5337897..6384cf9420b8 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Type.h +++ b/contrib/llvm-project/clang/include/clang/AST/Type.h @@ -34,10 +34,9 @@ #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator_range.h" @@ -51,12 +50,14 @@ #include <cstddef> #include <cstdint> #include <cstring> +#include <optional> #include <string> #include <type_traits> #include <utility> namespace clang { +class BTFTypeTagAttr; class ExtQuals; class QualType; class ConceptDecl; @@ -129,6 +130,7 @@ class TemplateArgumentLoc; class TemplateTypeParmDecl; class TypedefNameDecl; class UnresolvedUsingTypenameDecl; +class UsingShadowDecl; using CanQualType = CanQual<Type>; @@ -263,16 +265,31 @@ public: bool hasOnlyConst() const { return Mask == Const; } void removeConst() { Mask &= ~Const; } void addConst() { Mask |= Const; } + Qualifiers withConst() const { + Qualifiers Qs = *this; + Qs.addConst(); + return Qs; + } bool hasVolatile() const { return Mask & Volatile; } bool hasOnlyVolatile() const { return Mask == Volatile; } void removeVolatile() { Mask &= ~Volatile; } void addVolatile() { Mask |= Volatile; } + Qualifiers withVolatile() const { + Qualifiers Qs = *this; + Qs.addVolatile(); + return Qs; + } bool hasRestrict() const { return Mask & Restrict; } bool hasOnlyRestrict() const { return Mask == Restrict; } void removeRestrict() { Mask &= ~Restrict; } void addRestrict() { Mask |= Restrict; } + Qualifiers withRestrict() const { + Qualifiers Qs = *this; + Qs.addRestrict(); + return Qs; + } bool hasCVRQualifiers() const { return getCVRQualifiers(); } unsigned getCVRQualifiers() const { return Mask & CVRMask; } @@ -495,7 +512,12 @@ public: (A == LangAS::Default && (B == LangAS::sycl_private || B == LangAS::sycl_local || B == LangAS::sycl_global || B == LangAS::sycl_global_device || - B == LangAS::sycl_global_host)); + B == LangAS::sycl_global_host)) || + // In HIP device compilation, any cuda address space is allowed + // to implicitly cast into the default address space. + (A == LangAS::Default && + (B == LangAS::cuda_constant || B == LangAS::cuda_device || + B == LangAS::cuda_shared)); } /// Returns true if the address space in these qualifiers is equal to or @@ -602,6 +624,47 @@ private: static const uint32_t AddressSpaceShift = 9; }; +class QualifiersAndAtomic { + Qualifiers Quals; + bool HasAtomic; + +public: + QualifiersAndAtomic() : HasAtomic(false) {} + QualifiersAndAtomic(Qualifiers Quals, bool HasAtomic) + : Quals(Quals), HasAtomic(HasAtomic) {} + + operator Qualifiers() const { return Quals; } + + bool hasVolatile() const { return Quals.hasVolatile(); } + bool hasConst() const { return Quals.hasConst(); } + bool hasRestrict() const { return Quals.hasRestrict(); } + bool hasAtomic() const { return HasAtomic; } + + void addVolatile() { Quals.addVolatile(); } + void addConst() { Quals.addConst(); } + void addRestrict() { Quals.addRestrict(); } + void addAtomic() { HasAtomic = true; } + + void removeVolatile() { Quals.removeVolatile(); } + void removeConst() { Quals.removeConst(); } + void removeRestrict() { Quals.removeRestrict(); } + void removeAtomic() { HasAtomic = false; } + + QualifiersAndAtomic withVolatile() { + return {Quals.withVolatile(), HasAtomic}; + } + QualifiersAndAtomic withConst() { return {Quals.withConst(), HasAtomic}; } + QualifiersAndAtomic withRestrict() { + return {Quals.withRestrict(), HasAtomic}; + } + QualifiersAndAtomic withAtomic() { return {Quals, true}; } + + QualifiersAndAtomic &operator+=(Qualifiers RHS) { + Quals += RHS; + return *this; + } +}; + /// A std::pair-like structure for storing a qualified type split /// into its local qualifiers and its locally-unqualified type. struct SplitQualType { @@ -651,6 +714,12 @@ enum class ObjCSubstitutionContext { Superclass, }; +/// The kind of 'typeof' expression we're after. +enum class TypeOfKind : uint8_t { + Qualified, + Unqualified, +}; + /// A (possibly-)qualified type. /// /// For efficiency, we don't store CV-qualified types as nodes on their @@ -695,6 +764,8 @@ public: unsigned getLocalFastQualifiers() const { return Value.getInt(); } void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); } + bool UseExcessPrecision(const ASTContext &Ctx); + /// Retrieves a pointer to the underlying (unqualified) type. /// /// This function requires that the type not be NULL. If the type might be @@ -734,6 +805,9 @@ public: return Value.getPointer().isNull(); } + // Determines if a type can form `T&`. + bool isReferenceable() const; + /// Determine whether this particular QualType instance has the /// "const" qualifier set, without looking through typedefs that may have /// added "const" at a different level. @@ -744,6 +818,26 @@ public: /// Determine whether this type is const-qualified. bool isConstQualified() const; + enum class NonConstantStorageReason { + MutableField, + NonConstNonReferenceType, + NonTrivialCtor, + NonTrivialDtor, + }; + /// Determine whether instances of this type can be placed in immutable + /// storage. + /// If ExcludeCtor is true, the duration when the object's constructor runs + /// will not be considered. The caller will need to verify that the object is + /// not written to during its construction. ExcludeDtor works similarly. + std::optional<NonConstantStorageReason> + isNonConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, + bool ExcludeDtor); + + bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, + bool ExcludeDtor) { + return !isNonConstantStorage(Ctx, ExcludeCtor, ExcludeDtor); + } + /// Determine whether this particular QualType instance has the /// "restrict" qualifier set, without looking through typedefs that may have /// added "restrict" at a different level. @@ -823,6 +917,14 @@ public: /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(const ASTContext &Context) const; + /// Return true if this is a trivially copyable type + bool isTriviallyCopyConstructibleType(const ASTContext &Context) const; + + /// Return true if this is a trivially relocatable type. + bool isTriviallyRelocatableType(const ASTContext &Context) const; + + /// Return true if this is a trivially equality comparable type. + bool isTriviallyEqualityComparableType(const ASTContext &Context) const; /// Returns true if it is a class and it might be dynamic. bool mayBeDynamicClass() const; @@ -830,6 +932,15 @@ public: /// Returns true if it is not a class or if the class might not be dynamic. bool mayBeNotDynamicClass() const; + /// Returns true if it is a WebAssembly Reference Type. + bool isWebAssemblyReferenceType() const; + + /// Returns true if it is a WebAssembly Externref Type. + bool isWebAssemblyExternrefType() const; + + /// Returns true if it is a WebAssembly Funcref Type. + bool isWebAssemblyFuncrefType() const; + // Don't promise in the API that anything besides 'const' can be // easily added. @@ -870,7 +981,6 @@ public: void removeLocalConst(); void removeLocalVolatile(); void removeLocalRestrict(); - void removeLocalCVRQualifiers(unsigned Mask); void removeLocalFastQualifiers() { Value.setInt(0); } void removeLocalFastQualifiers(unsigned Mask) { @@ -924,6 +1034,10 @@ public: /// The resulting type might still be qualified if it's sugar for an array /// type. To strip qualifiers even from within a sugared array type, use /// ASTContext::getUnqualifiedArrayType. + /// + /// Note: In C, the _Atomic qualifier is special (see C23 6.2.5p32 for + /// details), and it is not stripped by this function. Use + /// getAtomicUnqualifiedType() to strip qualifiers including _Atomic. inline QualType getUnqualifiedType() const; /// Retrieve the unqualified variant of the given type, removing as little @@ -1305,6 +1419,8 @@ private: static bool hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD); }; +raw_ostream &operator<<(raw_ostream &OS, QualType QT); + } // namespace clang namespace llvm { @@ -1370,7 +1486,8 @@ class ExtQualsTypeCommonBase { /// in three low bits on the QualType pointer; a fourth bit records whether /// the pointer is an ExtQuals node. The extended qualifiers (address spaces, /// Objective-C GC attributes) are much more rare. -class ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode { +class alignas(TypeAlignment) ExtQuals : public ExtQualsTypeCommonBase, + public llvm::FoldingSetNode { // NOTE: changing the fast qualifiers should be straightforward as // long as you don't make 'const' non-fast. // 1. Qualifiers: @@ -1456,6 +1573,10 @@ enum class AutoTypeKeyword { GNUAutoType }; +enum class ArraySizeModifier; +enum class ElaboratedTypeKeyword; +enum class VectorKind; + /// The base class of the type hierarchy. /// /// A central concept with types is that each type always has a canonical @@ -1482,7 +1603,7 @@ enum class AutoTypeKeyword { /// /// Types, once created, are immutable. /// -class alignas(8) Type : public ExtQualsTypeCommonBase { +class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { public: enum TypeClass { #define TYPE(Class, Base) Class, @@ -1498,22 +1619,28 @@ private: template <class T> friend class TypePropertyCache; /// TypeClass bitfield - Enum that specifies what subclass this belongs to. + LLVM_PREFERRED_TYPE(TypeClass) unsigned TC : 8; /// Store information on the type dependency. + LLVM_PREFERRED_TYPE(TypeDependence) unsigned Dependence : llvm::BitWidth<TypeDependence>; /// True if the cache (i.e. the bitfields here starting with /// 'Cache') is valid. + LLVM_PREFERRED_TYPE(bool) mutable unsigned CacheValid : 1; /// Linkage of this type. + LLVM_PREFERRED_TYPE(Linkage) mutable unsigned CachedLinkage : 3; /// Whether this type involves and local or unnamed types. + LLVM_PREFERRED_TYPE(bool) mutable unsigned CachedLocalOrUnnamed : 1; /// Whether this type comes from an AST file. + LLVM_PREFERRED_TYPE(bool) mutable unsigned FromAST : 1; bool isCacheValid() const { @@ -1539,34 +1666,41 @@ protected: class ArrayTypeBitfields { friend class ArrayType; + LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; /// CVR qualifiers from declarations like /// 'int X[static restrict 4]'. For function parameters only. + LLVM_PREFERRED_TYPE(Qualifiers) unsigned IndexTypeQuals : 3; /// Storage class qualifiers from declarations like /// 'int X[static restrict 4]'. For function parameters only. - /// Actually an ArrayType::ArraySizeModifier. + LLVM_PREFERRED_TYPE(ArraySizeModifier) unsigned SizeModifier : 3; }; + enum { NumArrayTypeBits = NumTypeBits + 6 }; class ConstantArrayTypeBitfields { friend class ConstantArrayType; - unsigned : NumTypeBits + 3 + 3; + LLVM_PREFERRED_TYPE(ArrayTypeBitfields) + unsigned : NumArrayTypeBits; /// Whether we have a stored size expression. + LLVM_PREFERRED_TYPE(bool) unsigned HasStoredSizeExpr : 1; }; class BuiltinTypeBitfields { friend class BuiltinType; + LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; /// The kind (BuiltinType::Kind) of builtin type this is. - unsigned Kind : 8; + static constexpr unsigned NumOfBuiltinTypeBits = 9; + unsigned Kind : NumOfBuiltinTypeBits; }; /// FunctionTypeBitfields store various bits belonging to FunctionProtoType. @@ -1576,15 +1710,18 @@ protected: friend class FunctionProtoType; friend class FunctionType; + LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; /// Extra information which affects how the function is called, like /// regparm and the calling convention. + LLVM_PREFERRED_TYPE(CallingConv) unsigned ExtInfo : 13; /// The ref-qualifier associated with a \c FunctionProtoType. /// /// This is a value of type \c RefQualifierKind. + LLVM_PREFERRED_TYPE(RefQualifierKind) unsigned RefQualifier : 2; /// Used only by FunctionProtoType, put here to pack with the @@ -1593,8 +1730,10 @@ protected: /// /// C++ 8.3.5p4: The return type, the parameter type list and the /// cv-qualifier-seq, [...], are part of the function type. + LLVM_PREFERRED_TYPE(Qualifiers) unsigned FastTypeQuals : Qualifiers::FastWidth; /// Whether this function has extended Qualifiers. + LLVM_PREFERRED_TYPE(bool) unsigned HasExtQuals : 1; /// The number of parameters this function has, not counting '...'. @@ -1604,21 +1743,30 @@ protected: unsigned NumParams : 16; /// The type of exception specification this function has. + LLVM_PREFERRED_TYPE(ExceptionSpecificationType) unsigned ExceptionSpecType : 4; /// Whether this function has extended parameter information. + LLVM_PREFERRED_TYPE(bool) unsigned HasExtParameterInfos : 1; + /// Whether this function has extra bitfields for the prototype. + LLVM_PREFERRED_TYPE(bool) + unsigned HasExtraBitfields : 1; + /// Whether the function is variadic. + LLVM_PREFERRED_TYPE(bool) unsigned Variadic : 1; /// Whether this function has a trailing return type. + LLVM_PREFERRED_TYPE(bool) unsigned HasTrailingReturn : 1; }; class ObjCObjectTypeBitfields { friend class ObjCObjectType; + LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; /// The number of type arguments stored directly on this object type. @@ -1628,12 +1776,14 @@ protected: unsigned NumProtocols : 6; /// Whether this is a "kindof" type. + LLVM_PREFERRED_TYPE(bool) unsigned IsKindOf : 1; }; class ReferenceTypeBitfields { friend class ReferenceType; + LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; /// True if the type was originally spelled with an lvalue sigil. @@ -1647,31 +1797,36 @@ protected: /// ref &&a; // lvalue, inner ref /// rvref &a; // lvalue, inner ref, spelled lvalue /// rvref &&a; // rvalue, inner ref + LLVM_PREFERRED_TYPE(bool) unsigned SpelledAsLValue : 1; /// True if the inner type is a reference type. This only happens /// in non-canonical forms. + LLVM_PREFERRED_TYPE(bool) unsigned InnerRef : 1; }; class TypeWithKeywordBitfields { friend class TypeWithKeyword; + LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; /// An ElaboratedTypeKeyword. 8 bits for efficient access. + LLVM_PREFERRED_TYPE(ElaboratedTypeKeyword) unsigned Keyword : 8; }; - enum { NumTypeWithKeywordBits = 8 }; + enum { NumTypeWithKeywordBits = NumTypeBits + 8 }; class ElaboratedTypeBitfields { friend class ElaboratedType; - unsigned : NumTypeBits; + LLVM_PREFERRED_TYPE(TypeWithKeywordBitfields) unsigned : NumTypeWithKeywordBits; /// Whether the ElaboratedType has a trailing OwnedTagDecl. + LLVM_PREFERRED_TYPE(bool) unsigned HasOwnedTagDecl : 1; }; @@ -1679,11 +1834,13 @@ protected: friend class VectorType; friend class DependentVectorType; + LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; /// The kind of vector, either a generic vector type or some /// target-specific vector type such as for AltiVec or Neon. - unsigned VecKind : 3; + LLVM_PREFERRED_TYPE(VectorKind) + unsigned VecKind : 4; /// The number of elements in the vector. uint32_t NumElements; }; @@ -1691,19 +1848,22 @@ protected: class AttributedTypeBitfields { friend class AttributedType; + LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; - /// An AttributedType::Kind + LLVM_PREFERRED_TYPE(attr::Kind) unsigned AttrKind : 32 - NumTypeBits; }; class AutoTypeBitfields { friend class AutoType; + LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; /// Was this placeholder type spelled as 'auto', 'decltype(auto)', /// or '__auto_type'? AutoTypeKeyword value. + LLVM_PREFERRED_TYPE(AutoTypeKeyword) unsigned Keyword : 2; /// The number of template arguments in the type-constraints, which is @@ -1716,27 +1876,82 @@ protected: unsigned NumArgs; }; + class TypeOfBitfields { + friend class TypeOfType; + friend class TypeOfExprType; + + LLVM_PREFERRED_TYPE(TypeBitfields) + unsigned : NumTypeBits; + LLVM_PREFERRED_TYPE(bool) + unsigned IsUnqual : 1; // If true: typeof_unqual, else: typeof + }; + + class UsingBitfields { + friend class UsingType; + + LLVM_PREFERRED_TYPE(TypeBitfields) + unsigned : NumTypeBits; + + /// True if the underlying type is different from the declared one. + LLVM_PREFERRED_TYPE(bool) + unsigned hasTypeDifferentFromDecl : 1; + }; + + class TypedefBitfields { + friend class TypedefType; + + LLVM_PREFERRED_TYPE(TypeBitfields) + unsigned : NumTypeBits; + + /// True if the underlying type is different from the declared one. + LLVM_PREFERRED_TYPE(bool) + unsigned hasTypeDifferentFromDecl : 1; + }; + + class SubstTemplateTypeParmTypeBitfields { + friend class SubstTemplateTypeParmType; + + LLVM_PREFERRED_TYPE(TypeBitfields) + unsigned : NumTypeBits; + + LLVM_PREFERRED_TYPE(bool) + unsigned HasNonCanonicalUnderlyingType : 1; + + // The index of the template parameter this substitution represents. + unsigned Index : 15; + + /// Represents the index within a pack if this represents a substitution + /// from a pack expansion. This index starts at the end of the pack and + /// increments towards the beginning. + /// Positive non-zero number represents the index + 1. + /// Zero means this is not substituted from an expansion. + unsigned PackIndex : 16; + }; + class SubstTemplateTypeParmPackTypeBitfields { friend class SubstTemplateTypeParmPackType; + LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; + // The index of the template parameter this substitution represents. + unsigned Index : 16; + /// The number of template arguments in \c Arguments, which is /// expected to be able to hold at least 1024 according to [implimits]. /// However as this limit is somewhat easy to hit with template /// metaprogramming we'd prefer to keep it as large as possible. - /// At the moment it has been left as a non-bitfield since this type - /// safely fits in 64 bits as an unsigned, so there is no reason to - /// introduce the performance impact of a bitfield. - unsigned NumArgs; + unsigned NumArgs : 16; }; class TemplateSpecializationTypeBitfields { friend class TemplateSpecializationType; + LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; /// Whether this template specialization type is a substituted type alias. + LLVM_PREFERRED_TYPE(bool) unsigned TypeAlias : 1; /// The number of template arguments named in this class template @@ -1752,7 +1967,7 @@ protected: class DependentTemplateSpecializationTypeBitfields { friend class DependentTemplateSpecializationType; - unsigned : NumTypeBits; + LLVM_PREFERRED_TYPE(TypeWithKeywordBitfields) unsigned : NumTypeWithKeywordBits; /// The number of template arguments named in this class template @@ -1768,6 +1983,7 @@ protected: class PackExpansionTypeBitfields { friend class PackExpansionType; + LLVM_PREFERRED_TYPE(TypeBitfields) unsigned : NumTypeBits; /// The number of expansions that this pack expansion will @@ -1790,6 +2006,9 @@ protected: ConstantArrayTypeBitfields ConstantArrayTypeBits; AttributedTypeBitfields AttributedTypeBits; AutoTypeBitfields AutoTypeBits; + TypeOfBitfields TypeOfBits; + TypedefBitfields TypedefBits; + UsingBitfields UsingBits; BuiltinTypeBitfields BuiltinTypeBits; FunctionTypeBitfields FunctionTypeBits; ObjCObjectTypeBitfields ObjCObjectTypeBits; @@ -1797,6 +2016,7 @@ protected: TypeWithKeywordBitfields TypeWithKeywordBits; ElaboratedTypeBitfields ElaboratedTypeBits; VectorTypeBitfields VectorTypeBits; + SubstTemplateTypeParmTypeBitfields SubstTemplateTypeParmTypeBits; SubstTemplateTypeParmPackTypeBitfields SubstTemplateTypeParmPackTypeBits; TemplateSpecializationTypeBitfields TemplateSpecializationTypeBits; DependentTemplateSpecializationTypeBitfields @@ -1818,15 +2038,16 @@ protected: Type(TypeClass tc, QualType canon, TypeDependence Dependence) : ExtQualsTypeCommonBase(this, canon.isNull() ? QualType(this_(), 0) : canon) { - static_assert(sizeof(*this) <= 8 + sizeof(ExtQualsTypeCommonBase), + static_assert(sizeof(*this) <= + alignof(decltype(*this)) + sizeof(ExtQualsTypeCommonBase), "changing bitfields changed sizeof(Type)!"); - static_assert(alignof(decltype(*this)) % sizeof(void *) == 0, + static_assert(alignof(decltype(*this)) % TypeAlignment == 0, "Insufficient alignment!"); TypeBits.TC = tc; TypeBits.Dependence = static_cast<unsigned>(Dependence); TypeBits.CacheValid = false; TypeBits.CachedLocalOrUnnamed = false; - TypeBits.CachedLinkage = NoLinkage; + TypeBits.CachedLinkage = llvm::to_underlying(Linkage::Invalid); TypeBits.FromAST = false; } @@ -1894,16 +2115,43 @@ public: bool isSizelessType() const; bool isSizelessBuiltinType() const; + /// Returns true for all scalable vector types. + bool isSizelessVectorType() const; + + /// Returns true for SVE scalable vector types. + bool isSVESizelessBuiltinType() const; + + /// Returns true for RVV scalable vector types. + bool isRVVSizelessBuiltinType() const; + + /// Check if this is a WebAssembly Externref Type. + bool isWebAssemblyExternrefType() const; + + /// Returns true if this is a WebAssembly table type: either an array of + /// reference types, or a pointer to a reference type (which can only be + /// created by array to pointer decay). + bool isWebAssemblyTableType() const; + /// Determines if this is a sizeless type supported by the /// 'arm_sve_vector_bits' type attribute, which can be applied to a single /// SVE vector or predicate, excluding tuple types such as svint32x4_t. - bool isVLSTBuiltinType() const; + bool isSveVLSBuiltinType() const; /// Returns the representative type for the element of an SVE builtin type. /// This is used to represent fixed-length SVE vectors created with the /// 'arm_sve_vector_bits' type attribute as VectorType. QualType getSveEltType(const ASTContext &Ctx) const; + /// Determines if this is a sizeless type supported by the + /// 'riscv_rvv_vector_bits' type attribute, which can be applied to a single + /// RVV vector or mask. + bool isRVVVLSBuiltinType() const; + + /// Returns the representative type for the element of an RVV builtin type. + /// This is used to represent fixed-length RVV vectors created with the + /// 'riscv_rvv_vector_bits' type attribute as VectorType. + QualType getRVVEltType(const ASTContext &Ctx) const; + /// Types are partitioned into 3 broad categories (C99 6.2.5p1): /// object types, function types, and incomplete types. @@ -1998,6 +2246,7 @@ public: bool isFloat16Type() const; // C11 extension ISO/IEC TS 18661 bool isBFloat16Type() const; bool isFloat128Type() const; + bool isIbm128Type() const; bool isRealType() const; // C99 6.2.5p17 (real floating + integer) bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating) bool isVoidType() const; // C99 6.2.5p19 @@ -2039,6 +2288,7 @@ public: bool isComplexIntegerType() const; // GCC _Complex integer type. bool isVectorType() const; // GCC vector type. bool isExtVectorType() const; // Extended vector type. + bool isExtVectorBoolType() const; // Extended vector type with bool element. bool isMatrixType() const; // Matrix type. bool isConstantMatrixType() const; // Constant matrix type. bool isDependentAddressSpaceType() const; // value-dependent address space qualifier @@ -2093,7 +2343,8 @@ public: bool isObjCARCBridgableType() const; bool isCARCBridgableType() const; bool isTemplateTypeParmType() const; // C++ template type parameter - bool isNullPtrType() const; // C++11 std::nullptr_t + bool isNullPtrType() const; // C++11 std::nullptr_t or + // C23 nullptr_t bool isNothrowT() const; // C++ std::nothrow_t bool isAlignValT() const; // C++17 std::align_val_t bool isStdByteType() const; // C++17 std::byte @@ -2122,7 +2373,7 @@ public: bool isOCLExtOpaqueType() const; // Any OpenCL extension type bool isPipeType() const; // OpenCL pipe type - bool isExtIntType() const; // Extended Int Type + bool isBitIntType() const; // Bit-precise integer type bool isOpenCLSpecificType() const; // Any OpenCL specific type /// Determines if this type, which must satisfy @@ -2337,9 +2588,6 @@ public: /// removing any typedefs, typeofs, etc., as well as any qualifiers. const Type *getUnqualifiedDesugaredType() const; - /// More type predicates useful for type checking/promotion - bool isPromotableIntegerType() const; // C99 6.3.1.1p2 - /// Return true if this is an integer type that is /// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..], /// or an enum decl which has a signed representation. @@ -2415,7 +2663,7 @@ public: /// Note that nullability is only captured as sugar within the type /// system, not as part of the canonical type, so nullability will /// be lost by canonicalization and desugaring. - Optional<NullabilityKind> getNullability(const ASTContext &context) const; + std::optional<NullabilityKind> getNullability() const; /// Determine whether the given type can have a nullability /// specifier applied to it, i.e., if it is any kind of pointer type. @@ -2439,7 +2687,7 @@ public: /// the type parameters of the given declaration context in any type described /// within that context, or an empty optional to indicate that no /// substitution is required. - Optional<ArrayRef<QualType>> + std::optional<ArrayRef<QualType>> getObjCSubstitutions(const DeclContext *dc) const; /// Determines if this is an ObjC interface type that may accept type @@ -2460,6 +2708,7 @@ public: /// This will check for a TypedefType by removing any existing sugar /// until it reaches a TypedefType or a non-sugared type. template <> const TypedefType *Type::getAs() const; +template <> const UsingType *Type::getAs() const; /// This will check for a TemplateSpecializationType by removing any /// existing sugar until it reaches a TemplateSpecializationType or a @@ -2502,6 +2751,9 @@ public: // RVV Types #define RVV_TYPE(Name, Id, SingletonId) Id, #include "clang/Basic/RISCVVTypes.def" +// WebAssembly reference types +#define WASM_TYPE(Name, Id, SingletonId) Id, +#include "clang/Basic/WebAssemblyReferenceTypes.def" // All other builtin types #define BUILTIN_TYPE(Id, SingletonId) Id, #define LAST_BUILTIN_TYPE(Id) LastKind = Id @@ -2515,6 +2767,10 @@ private: : Type(Builtin, QualType(), K == Dependent ? TypeDependence::DependentInstantiation : TypeDependence::None) { + static_assert(Kind::LastKind < + (1 << BuiltinTypeBitfields::NumOfBuiltinTypeBits) && + "Defined builtin type exceeds the allocated space for serial " + "numbering"); BuiltinTypeBits.Kind = K; } @@ -2545,9 +2801,13 @@ public: } bool isFloatingPoint() const { - return getKind() >= Half && getKind() <= Float128; + return getKind() >= Half && getKind() <= Ibm128; } + bool isSVEBool() const { return getKind() == Kind::SveBool; } + + bool isSVECount() const { return getKind() == Kind::SveCount; } + /// Determines whether the given kind corresponds to a placeholder type. static bool isPlaceholderTypeKind(Kind K) { return K >= Overload; @@ -2873,17 +3133,14 @@ public: } }; +/// Capture whether this is a normal array (e.g. int X[4]) +/// an array with a static size (e.g. int X[static 4]), or an array +/// with a star size (e.g. int X[*]). +/// 'static' is only allowed on function parameters. +enum class ArraySizeModifier { Normal, Static, Star }; + /// Represents an array type, per C99 6.7.5.2 - Array Declarators. class ArrayType : public Type, public llvm::FoldingSetNode { -public: - /// Capture whether this is a normal array (e.g. int X[4]) - /// an array with a static size (e.g. int X[static 4]), or an array - /// with a star size (e.g. int X[*]). - /// 'static' is only allowed on function parameters. - enum ArraySizeModifier { - Normal, Static, Star - }; - private: /// The element type of the array. QualType ElementType; @@ -2958,6 +3215,8 @@ public: QualType ElementType, const llvm::APInt &NumElements); + unsigned getNumAddressingBits(const ASTContext &Context) const; + /// Determine the maximum number of active bits that an array's size /// can require, which limits the maximum size of the array. static unsigned getMaxSizeBits(const ASTContext &Context); @@ -3005,7 +3264,7 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, QualType ET, ArraySizeModifier SizeMod, unsigned TypeQuals) { ID.AddPointer(ET.getAsOpaquePtr()); - ID.AddInteger(SizeMod); + ID.AddInteger(llvm::to_underlying(SizeMod)); ID.AddInteger(TypeQuals); } }; @@ -3081,8 +3340,6 @@ public: class DependentSizedArrayType : public ArrayType { friend class ASTContext; // ASTContext creates these. - const ASTContext &Context; - /// An assignment expression that will instantiate to the /// size of the array. /// @@ -3093,8 +3350,8 @@ class DependentSizedArrayType : public ArrayType { /// The range spanned by the left and right array brackets. SourceRange Brackets; - DependentSizedArrayType(const ASTContext &Context, QualType et, QualType can, - Expr *e, ArraySizeModifier sm, unsigned tq, + DependentSizedArrayType(QualType et, QualType can, Expr *e, + ArraySizeModifier sm, unsigned tq, SourceRange brackets); public: @@ -3117,7 +3374,7 @@ public: return T->getTypeClass() == DependentSizedArray; } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getElementType(), getSizeModifier(), getIndexTypeCVRQualifiers(), getSizeExpr()); } @@ -3141,14 +3398,12 @@ public: class DependentAddressSpaceType : public Type, public llvm::FoldingSetNode { friend class ASTContext; - const ASTContext &Context; Expr *AddrSpaceExpr; QualType PointeeType; SourceLocation loc; - DependentAddressSpaceType(const ASTContext &Context, QualType PointeeType, - QualType can, Expr *AddrSpaceExpr, - SourceLocation loc); + DependentAddressSpaceType(QualType PointeeType, QualType can, + Expr *AddrSpaceExpr, SourceLocation loc); public: Expr *getAddrSpaceExpr() const { return AddrSpaceExpr; } @@ -3162,7 +3417,7 @@ public: return T->getTypeClass() == DependentAddressSpace; } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getPointeeType(), getAddrSpaceExpr()); } @@ -3183,7 +3438,6 @@ public: class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { friend class ASTContext; - const ASTContext &Context; Expr *SizeExpr; /// The element type of the array. @@ -3191,8 +3445,8 @@ class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { SourceLocation loc; - DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType, - QualType can, Expr *SizeExpr, SourceLocation loc); + DependentSizedExtVectorType(QualType ElementType, QualType can, + Expr *SizeExpr, SourceLocation loc); public: Expr *getSizeExpr() const { return SizeExpr; } @@ -3206,7 +3460,7 @@ public: return T->getTypeClass() == DependentSizedExtVector; } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getElementType(), getSizeExpr()); } @@ -3214,40 +3468,44 @@ public: QualType ElementType, Expr *SizeExpr); }; +enum class VectorKind { + /// not a target-specific vector type + Generic, -/// Represents a GCC generic vector type. This type is created using -/// __attribute__((vector_size(n)), where "n" specifies the vector size in -/// bytes; or from an Altivec __vector or vector declaration. -/// Since the constructor takes the number of vector elements, the -/// client is responsible for converting the size into the number of elements. -class VectorType : public Type, public llvm::FoldingSetNode { -public: - enum VectorKind { - /// not a target-specific vector type - GenericVector, + /// is AltiVec vector + AltiVecVector, - /// is AltiVec vector - AltiVecVector, + /// is AltiVec 'vector Pixel' + AltiVecPixel, - /// is AltiVec 'vector Pixel' - AltiVecPixel, + /// is AltiVec 'vector bool ...' + AltiVecBool, - /// is AltiVec 'vector bool ...' - AltiVecBool, + /// is ARM Neon vector + Neon, - /// is ARM Neon vector - NeonVector, + /// is ARM Neon polynomial vector + NeonPoly, - /// is ARM Neon polynomial vector - NeonPolyVector, + /// is AArch64 SVE fixed-length data vector + SveFixedLengthData, - /// is AArch64 SVE fixed-length data vector - SveFixedLengthDataVector, + /// is AArch64 SVE fixed-length predicate vector + SveFixedLengthPredicate, - /// is AArch64 SVE fixed-length predicate vector - SveFixedLengthPredicateVector - }; + /// is RISC-V RVV fixed-length data vector + RVVFixedLengthData, + + /// is RISC-V RVV fixed-length mask vector + RVVFixedLengthMask, +}; +/// Represents a GCC generic vector type. This type is created using +/// __attribute__((vector_size(n)), where "n" specifies the vector size in +/// bytes; or from an Altivec __vector or vector declaration. +/// Since the constructor takes the number of vector elements, the +/// client is responsible for converting the size into the number of elements. +class VectorType : public Type, public llvm::FoldingSetNode { protected: friend class ASTContext; // ASTContext creates these. @@ -3282,7 +3540,7 @@ public: ID.AddPointer(ElementType.getAsOpaquePtr()); ID.AddInteger(NumElements); ID.AddInteger(TypeClass); - ID.AddInteger(VecKind); + ID.AddInteger(llvm::to_underlying(VecKind)); } static bool classof(const Type *T) { @@ -3302,21 +3560,19 @@ public: class DependentVectorType : public Type, public llvm::FoldingSetNode { friend class ASTContext; - const ASTContext &Context; QualType ElementType; Expr *SizeExpr; SourceLocation Loc; - DependentVectorType(const ASTContext &Context, QualType ElementType, - QualType CanonType, Expr *SizeExpr, - SourceLocation Loc, VectorType::VectorKind vecKind); + DependentVectorType(QualType ElementType, QualType CanonType, Expr *SizeExpr, + SourceLocation Loc, VectorKind vecKind); public: Expr *getSizeExpr() const { return SizeExpr; } QualType getElementType() const { return ElementType; } SourceLocation getAttributeLoc() const { return Loc; } - VectorType::VectorKind getVectorKind() const { - return VectorType::VectorKind(VectorTypeBits.VecKind); + VectorKind getVectorKind() const { + return VectorKind(VectorTypeBits.VecKind); } bool isSugared() const { return false; } @@ -3326,13 +3582,13 @@ public: return T->getTypeClass() == DependentVector; } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getElementType(), getSizeExpr(), getVectorKind()); } static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, QualType ElementType, const Expr *SizeExpr, - VectorType::VectorKind VecKind); + VectorKind VecKind); }; /// ExtVectorType - Extended vector type. This type is created using @@ -3345,7 +3601,8 @@ class ExtVectorType : public VectorType { friend class ASTContext; // ASTContext creates these. ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) - : VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {} + : VectorType(ExtVector, vecType, nElements, canonType, + VectorKind::Generic) {} public: static int getPointAccessorIdx(char c) { @@ -3427,7 +3684,7 @@ public: QualType getElementType() const { return ElementType; } /// Valid elements types are the following: - /// * an integer type (as in C2x 6.2.5p19), but excluding enumerated types + /// * an integer type (as in C23 6.2.5p22), but excluding enumerated types /// and _Bool /// * the standard floating types float or double /// * a half-precision floating point type, if one is supported on the target @@ -3450,10 +3707,6 @@ class ConstantMatrixType final : public MatrixType { protected: friend class ASTContext; - /// The element type of the matrix. - // FIXME: Appears to be unused? There is also MatrixType::ElementType... - QualType ElementType; - /// Number of rows and columns. unsigned NumRows; unsigned NumColumns; @@ -3512,30 +3765,24 @@ public: class DependentSizedMatrixType final : public MatrixType { friend class ASTContext; - const ASTContext &Context; Expr *RowExpr; Expr *ColumnExpr; SourceLocation loc; - DependentSizedMatrixType(const ASTContext &Context, QualType ElementType, - QualType CanonicalType, Expr *RowExpr, - Expr *ColumnExpr, SourceLocation loc); + DependentSizedMatrixType(QualType ElementType, QualType CanonicalType, + Expr *RowExpr, Expr *ColumnExpr, SourceLocation loc); public: - QualType getElementType() const { return ElementType; } Expr *getRowExpr() const { return RowExpr; } Expr *getColumnExpr() const { return ColumnExpr; } SourceLocation getAttributeLoc() const { return loc; } - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - static bool classof(const Type *T) { return T->getTypeClass() == DependentSizedMatrix; } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getElementType(), getRowExpr(), getColumnExpr()); } @@ -3787,13 +4034,64 @@ public: /// A simple holder for various uncommon bits which do not fit in /// FunctionTypeBitfields. Aligned to alignof(void *) to maintain the - /// alignment of subsequent objects in TrailingObjects. You must update - /// hasExtraBitfields in FunctionProtoType after adding extra data here. + /// alignment of subsequent objects in TrailingObjects. struct alignas(void *) FunctionTypeExtraBitfields { /// The number of types in the exception specification. /// A whole unsigned is not needed here and according to /// [implimits] 8 bits would be enough here. - unsigned NumExceptionType; + unsigned NumExceptionType : 10; + + LLVM_PREFERRED_TYPE(bool) + unsigned HasArmTypeAttributes : 1; + + FunctionTypeExtraBitfields() + : NumExceptionType(0), HasArmTypeAttributes(false) {} + }; + + /// The AArch64 SME ACLE (Arm C/C++ Language Extensions) define a number + /// of function type attributes that can be set on function types, including + /// function pointers. + enum AArch64SMETypeAttributes : unsigned { + SME_NormalFunction = 0, + SME_PStateSMEnabledMask = 1 << 0, + SME_PStateSMCompatibleMask = 1 << 1, + + // Describes the value of the state using ArmStateValue. + SME_ZAShift = 2, + SME_ZAMask = 0b111 << SME_ZAShift, + SME_ZT0Shift = 5, + SME_ZT0Mask = 0b111 << SME_ZT0Shift, + + SME_AttributeMask = + 0b111'111'11 // We can't support more than 8 bits because of + // the bitmask in FunctionTypeExtraBitfields. + }; + + enum ArmStateValue : unsigned { + ARM_None = 0, + ARM_Preserves = 1, + ARM_In = 2, + ARM_Out = 3, + ARM_InOut = 4, + }; + + static ArmStateValue getArmZAState(unsigned AttrBits) { + return (ArmStateValue)((AttrBits & SME_ZAMask) >> SME_ZAShift); + } + + static ArmStateValue getArmZT0State(unsigned AttrBits) { + return (ArmStateValue)((AttrBits & SME_ZT0Mask) >> SME_ZT0Shift); + } + + /// A holder for Arm type attributes as described in the Arm C/C++ + /// Language extensions which are not particularly common to all + /// types and therefore accounted separately from FunctionTypeBitfields. + struct alignas(void *) FunctionTypeArmAttributes { + /// Any AArch64 SME ACLE type attributes that need to be propagated + /// on declarations and function pointers. + unsigned AArch64SMEAttributes : 8; + + FunctionTypeArmAttributes() : AArch64SMEAttributes(SME_NormalFunction) {} }; protected: @@ -3804,7 +4102,10 @@ protected: } Qualifiers getFastTypeQuals() const { - return Qualifiers::fromFastMask(FunctionTypeBits.FastTypeQuals); + if (isFunctionProtoType()) + return Qualifiers::fromFastMask(FunctionTypeBits.FastTypeQuals); + + return Qualifiers(); } public: @@ -3889,7 +4190,8 @@ class FunctionProtoType final public llvm::FoldingSetNode, private llvm::TrailingObjects< FunctionProtoType, QualType, SourceLocation, - FunctionType::FunctionTypeExtraBitfields, FunctionType::ExceptionType, + FunctionType::FunctionTypeExtraBitfields, + FunctionType::FunctionTypeArmAttributes, FunctionType::ExceptionType, Expr *, FunctionDecl *, FunctionType::ExtParameterInfo, Qualifiers> { friend class ASTContext; // ASTContext creates these. friend TrailingObjects; @@ -3962,6 +4264,8 @@ public: ExceptionSpecInfo() = default; ExceptionSpecInfo(ExceptionSpecificationType EST) : Type(EST) {} + + void instantiate(); }; /// Extra information about a function prototype. ExtProtoInfo is not @@ -3969,24 +4273,44 @@ public: /// the various bits of extra information about a function prototype. struct ExtProtoInfo { FunctionType::ExtInfo ExtInfo; - bool Variadic : 1; - bool HasTrailingReturn : 1; + unsigned Variadic : 1; + unsigned HasTrailingReturn : 1; + unsigned AArch64SMEAttributes : 8; Qualifiers TypeQuals; RefQualifierKind RefQualifier = RQ_None; ExceptionSpecInfo ExceptionSpec; const ExtParameterInfo *ExtParameterInfos = nullptr; SourceLocation EllipsisLoc; - ExtProtoInfo() : Variadic(false), HasTrailingReturn(false) {} + ExtProtoInfo() + : Variadic(false), HasTrailingReturn(false), + AArch64SMEAttributes(SME_NormalFunction) {} ExtProtoInfo(CallingConv CC) - : ExtInfo(CC), Variadic(false), HasTrailingReturn(false) {} + : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), + AArch64SMEAttributes(SME_NormalFunction) {} ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &ESI) { ExtProtoInfo Result(*this); Result.ExceptionSpec = ESI; return Result; } + + bool requiresFunctionProtoTypeExtraBitfields() const { + return ExceptionSpec.Type == EST_Dynamic || + requiresFunctionProtoTypeArmAttributes(); + } + + bool requiresFunctionProtoTypeArmAttributes() const { + return AArch64SMEAttributes != SME_NormalFunction; + } + + void setArmSMEAttribute(AArch64SMETypeAttributes Kind, bool Enable = true) { + if (Enable) + AArch64SMEAttributes |= Kind; + else + AArch64SMEAttributes &= ~Kind; + } }; private: @@ -3998,6 +4322,10 @@ private: return isVariadic(); } + unsigned numTrailingObjects(OverloadToken<FunctionTypeArmAttributes>) const { + return hasArmTypeAttributes(); + } + unsigned numTrailingObjects(OverloadToken<FunctionTypeExtraBitfields>) const { return hasExtraBitfields(); } @@ -4078,15 +4406,18 @@ private: } /// Whether the trailing FunctionTypeExtraBitfields is present. - static bool hasExtraBitfields(ExceptionSpecificationType EST) { - // If the exception spec type is EST_Dynamic then we have > 0 exception - // types and the exact number is stored in FunctionTypeExtraBitfields. - return EST == EST_Dynamic; + bool hasExtraBitfields() const { + assert((getExceptionSpecType() != EST_Dynamic || + FunctionTypeBits.HasExtraBitfields) && + "ExtraBitfields are required for given ExceptionSpecType"); + return FunctionTypeBits.HasExtraBitfields; + } - /// Whether the trailing FunctionTypeExtraBitfields is present. - bool hasExtraBitfields() const { - return hasExtraBitfields(getExceptionSpecType()); + bool hasArmTypeAttributes() const { + return FunctionTypeBits.HasExtraBitfields && + getTrailingObjects<FunctionTypeExtraBitfields>() + ->HasArmTypeAttributes; } bool hasExtQualifiers() const { @@ -4102,7 +4433,7 @@ public: } ArrayRef<QualType> getParamTypes() const { - return llvm::makeArrayRef(param_type_begin(), param_type_end()); + return llvm::ArrayRef(param_type_begin(), param_type_end()); } ExtProtoInfo getExtProtoInfo() const { @@ -4115,6 +4446,7 @@ public: EPI.TypeQuals = getMethodQuals(); EPI.RefQualifier = getRefQualifier(); EPI.ExtParameterInfos = getExtParameterInfosOrNull(); + EPI.AArch64SMEAttributes = getAArch64SMEAttributes(); return EPI; } @@ -4247,10 +4579,9 @@ public: } using param_type_iterator = const QualType *; - using param_type_range = llvm::iterator_range<param_type_iterator>; - param_type_range param_types() const { - return param_type_range(param_type_begin(), param_type_end()); + ArrayRef<QualType> param_types() const { + return llvm::ArrayRef(param_type_begin(), param_type_end()); } param_type_iterator param_type_begin() const { @@ -4264,7 +4595,7 @@ public: using exception_iterator = const QualType *; ArrayRef<QualType> exceptions() const { - return llvm::makeArrayRef(exception_begin(), exception_end()); + return llvm::ArrayRef(exception_begin(), exception_end()); } exception_iterator exception_begin() const { @@ -4297,6 +4628,15 @@ public: return getTrailingObjects<ExtParameterInfo>(); } + /// Return a bitmask describing the SME attributes on the function type, see + /// AArch64SMETypeAttributes for their values. + unsigned getAArch64SMEAttributes() const { + if (!hasArmTypeAttributes()) + return SME_NormalFunction; + return getTrailingObjects<FunctionTypeArmAttributes>() + ->AArch64SMEAttributes; + } + ExtParameterInfo getExtParameterInfo(unsigned I) const { assert(I < getNumParams() && "parameter index out of range"); if (hasExtParameterInfos()) @@ -4370,11 +4710,45 @@ public: } }; -class TypedefType : public Type { - TypedefNameDecl *Decl; +class UsingType final : public Type, + public llvm::FoldingSetNode, + private llvm::TrailingObjects<UsingType, QualType> { + UsingShadowDecl *Found; + friend class ASTContext; // ASTContext creates these. + friend TrailingObjects; -private: + UsingType(const UsingShadowDecl *Found, QualType Underlying, QualType Canon); + +public: + UsingShadowDecl *getFoundDecl() const { return Found; } + QualType getUnderlyingType() const; + + bool isSugared() const { return true; } + + // This always has the 'same' type as declared, but not necessarily identical. + QualType desugar() const { return getUnderlyingType(); } + + // Internal helper, for debugging purposes. + bool typeMatchesDecl() const { return !UsingBits.hasTypeDifferentFromDecl; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Found, typeMatchesDecl() ? QualType() : getUnderlyingType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, const UsingShadowDecl *Found, + QualType Underlying) { + ID.AddPointer(Found); + if (!Underlying.isNull()) + Underlying.Profile(ID); + } + static bool classof(const Type *T) { return T->getTypeClass() == Using; } +}; + +class TypedefType final : public Type, + public llvm::FoldingSetNode, + private llvm::TrailingObjects<TypedefType, QualType> { + TypedefNameDecl *Decl; friend class ASTContext; // ASTContext creates these. + friend TrailingObjects; TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType underlying, QualType can); @@ -4383,8 +4757,23 @@ public: TypedefNameDecl *getDecl() const { return Decl; } bool isSugared() const { return true; } + + // This always has the 'same' type as declared, but not necessarily identical. QualType desugar() const; + // Internal helper, for debugging purposes. + bool typeMatchesDecl() const { return !TypedefBits.hasTypeDifferentFromDecl; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Decl, typeMatchesDecl() ? QualType() : desugar()); + } + static void Profile(llvm::FoldingSetNodeID &ID, const TypedefNameDecl *Decl, + QualType Underlying) { + ID.AddPointer(Decl); + if (!Underlying.isNull()) + Underlying.Profile(ID); + } + static bool classof(const Type *T) { return T->getTypeClass() == Typedef; } }; @@ -4420,18 +4809,25 @@ public: } }; -/// Represents a `typeof` (or __typeof__) expression (a GCC extension). +/// Represents a `typeof` (or __typeof__) expression (a C23 feature and GCC +/// extension) or a `typeof_unqual` expression (a C23 feature). class TypeOfExprType : public Type { Expr *TOExpr; protected: friend class ASTContext; // ASTContext creates these. - TypeOfExprType(Expr *E, QualType can = QualType()); + TypeOfExprType(Expr *E, TypeOfKind Kind, QualType Can = QualType()); public: Expr *getUnderlyingExpr() const { return TOExpr; } + /// Returns the kind of 'typeof' type this is. + TypeOfKind getKind() const { + return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified + : TypeOfKind::Qualified; + } + /// Remove a single level of sugar. QualType desugar() const; @@ -4447,42 +4843,54 @@ public: /// This class is used internally by the ASTContext to manage /// canonical, dependent types, only. Clients will only see instances /// of this class via TypeOfExprType nodes. -class DependentTypeOfExprType - : public TypeOfExprType, public llvm::FoldingSetNode { - const ASTContext &Context; - +class DependentTypeOfExprType : public TypeOfExprType, + public llvm::FoldingSetNode { public: - DependentTypeOfExprType(const ASTContext &Context, Expr *E) - : TypeOfExprType(E), Context(Context) {} + DependentTypeOfExprType(Expr *E, TypeOfKind Kind) : TypeOfExprType(E, Kind) {} - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Context, getUnderlyingExpr()); + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { + Profile(ID, Context, getUnderlyingExpr(), + getKind() == TypeOfKind::Unqualified); } static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - Expr *E); + Expr *E, bool IsUnqual); }; -/// Represents `typeof(type)`, a GCC extension. +/// Represents `typeof(type)`, a C23 feature and GCC extension, or +/// `typeof_unqual(type), a C23 feature. class TypeOfType : public Type { friend class ASTContext; // ASTContext creates these. QualType TOType; - TypeOfType(QualType T, QualType can) - : Type(TypeOf, can, T->getDependence()), TOType(T) { - assert(!isa<TypedefType>(can) && "Invalid canonical type"); + TypeOfType(QualType T, QualType Can, TypeOfKind Kind) + : Type(TypeOf, + Kind == TypeOfKind::Unqualified ? Can.getAtomicUnqualifiedType() + : Can, + T->getDependence()), + TOType(T) { + TypeOfBits.IsUnqual = Kind == TypeOfKind::Unqualified; } public: - QualType getUnderlyingType() const { return TOType; } + QualType getUnmodifiedType() const { return TOType; } /// Remove a single level of sugar. - QualType desugar() const { return getUnderlyingType(); } + QualType desugar() const { + QualType QT = getUnmodifiedType(); + return TypeOfBits.IsUnqual ? QT.getAtomicUnqualifiedType() : QT; + } /// Returns whether this type directly provides sugar. bool isSugared() const { return true; } + /// Returns the kind of 'typeof' type this is. + TypeOfKind getKind() const { + return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified + : TypeOfKind::Qualified; + } + static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; } }; @@ -4516,12 +4924,10 @@ public: /// canonical, dependent types, only. Clients will only see instances /// of this class via DecltypeType nodes. class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode { - const ASTContext &Context; - public: - DependentDecltypeType(const ASTContext &Context, Expr *E); + DependentDecltypeType(Expr *E, QualType UnderlyingTpe); - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getUnderlyingExpr()); } @@ -4533,7 +4939,8 @@ public: class UnaryTransformType : public Type { public: enum UTTKind { - EnumUnderlyingType +#define TRANSFORM_TYPE_TRAIT_DEF(Enum, _) Enum, +#include "clang/Basic/TransformTypeTraits.def" }; private: @@ -4714,9 +5121,11 @@ public: bool isMSTypeSpec() const; + bool isWebAssemblyFuncrefSpec() const; + bool isCallingConv() const; - llvm::Optional<NullabilityKind> getImmediateNullability() const; + std::optional<NullabilityKind> getImmediateNullability() const; /// Retrieve the attribute kind corresponding to the given /// nullability kind. @@ -4746,7 +5155,7 @@ public: /// to the underlying modified type. /// /// \returns the top-level nullability, if present. - static Optional<NullabilityKind> stripOuterNullability(QualType &T); + static std::optional<NullabilityKind> stripOuterNullability(QualType &T); void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getAttrKind(), ModifiedType, EquivalentType); @@ -4764,6 +5173,40 @@ public: } }; +class BTFTagAttributedType : public Type, public llvm::FoldingSetNode { +private: + friend class ASTContext; // ASTContext creates these + + QualType WrappedType; + const BTFTypeTagAttr *BTFAttr; + + BTFTagAttributedType(QualType Canon, QualType Wrapped, + const BTFTypeTagAttr *BTFAttr) + : Type(BTFTagAttributed, Canon, Wrapped->getDependence()), + WrappedType(Wrapped), BTFAttr(BTFAttr) {} + +public: + QualType getWrappedType() const { return WrappedType; } + const BTFTypeTagAttr *getAttr() const { return BTFAttr; } + + bool isSugared() const { return true; } + QualType desugar() const { return getWrappedType(); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, WrappedType, BTFAttr); + } + + static void Profile(llvm::FoldingSetNodeID &ID, QualType Wrapped, + const BTFTypeTagAttr *BTFAttr) { + ID.AddPointer(Wrapped.getAsOpaquePtr()); + ID.AddPointer(BTFAttr); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == BTFTagAttributed; + } +}; + class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these @@ -4843,40 +5286,60 @@ public: /// been replaced with these. They are used solely to record that a /// type was originally written as a template type parameter; /// therefore they are never canonical. -class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { +class SubstTemplateTypeParmType final + : public Type, + public llvm::FoldingSetNode, + private llvm::TrailingObjects<SubstTemplateTypeParmType, QualType> { friend class ASTContext; + friend class llvm::TrailingObjects<SubstTemplateTypeParmType, QualType>; - // The original type parameter. - const TemplateTypeParmType *Replaced; + Decl *AssociatedDecl; - SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon) - : Type(SubstTemplateTypeParm, Canon, Canon->getDependence()), - Replaced(Param) {} + SubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl, + unsigned Index, std::optional<unsigned> PackIndex); public: - /// Gets the template parameter that was substituted for. - const TemplateTypeParmType *getReplacedParameter() const { - return Replaced; - } - /// Gets the type that was substituted for the template /// parameter. QualType getReplacementType() const { - return getCanonicalTypeInternal(); + return SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType + ? *getTrailingObjects<QualType>() + : getCanonicalTypeInternal(); + } + + /// A template-like entity which owns the whole pattern being substituted. + /// This will usually own a set of template parameters, or in some + /// cases might even be a template parameter itself. + Decl *getAssociatedDecl() const { return AssociatedDecl; } + + /// Gets the template parameter declaration that was substituted for. + const TemplateTypeParmDecl *getReplacedParameter() const; + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getReplacedParameter()->getIndex()`. + unsigned getIndex() const { return SubstTemplateTypeParmTypeBits.Index; } + + std::optional<unsigned> getPackIndex() const { + if (SubstTemplateTypeParmTypeBits.PackIndex == 0) + return std::nullopt; + return SubstTemplateTypeParmTypeBits.PackIndex - 1; } bool isSugared() const { return true; } QualType desugar() const { return getReplacementType(); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getReplacedParameter(), getReplacementType()); + Profile(ID, getReplacementType(), getAssociatedDecl(), getIndex(), + getPackIndex()); } - static void Profile(llvm::FoldingSetNodeID &ID, - const TemplateTypeParmType *Replaced, - QualType Replacement) { - ID.AddPointer(Replaced); - ID.AddPointer(Replacement.getAsOpaquePtr()); + static void Profile(llvm::FoldingSetNodeID &ID, QualType Replacement, + const Decl *AssociatedDecl, unsigned Index, + std::optional<unsigned> PackIndex) { + Replacement.Profile(ID); + ID.AddPointer(AssociatedDecl); + ID.AddInteger(Index); + ID.AddInteger(PackIndex ? *PackIndex - 1 : 0); } static bool classof(const Type *T) { @@ -4899,24 +5362,33 @@ public: class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { friend class ASTContext; - /// The original type parameter. - const TemplateTypeParmType *Replaced; - /// A pointer to the set of template arguments that this /// parameter pack is instantiated with. const TemplateArgument *Arguments; - SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, - QualType Canon, + llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal; + + SubstTemplateTypeParmPackType(QualType Canon, Decl *AssociatedDecl, + unsigned Index, bool Final, const TemplateArgument &ArgPack); public: - IdentifierInfo *getIdentifier() const { return Replaced->getIdentifier(); } + IdentifierInfo *getIdentifier() const; - /// Gets the template parameter that was substituted for. - const TemplateTypeParmType *getReplacedParameter() const { - return Replaced; - } + /// A template-like entity which owns the whole pattern being substituted. + /// This will usually own a set of template parameters, or in some + /// cases might even be a template parameter itself. + Decl *getAssociatedDecl() const; + + /// Gets the template parameter declaration that was substituted for. + const TemplateTypeParmDecl *getReplacedParameter() const; + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getReplacedParameter()->getIndex()`. + unsigned getIndex() const { return SubstTemplateTypeParmPackTypeBits.Index; } + + // When true the substitution will be 'Final' (subst node won't be placed). + bool getFinal() const; unsigned getNumArgs() const { return SubstTemplateTypeParmPackTypeBits.NumArgs; @@ -4928,8 +5400,8 @@ public: TemplateArgument getArgumentPack() const; void Profile(llvm::FoldingSetNodeID &ID); - static void Profile(llvm::FoldingSetNodeID &ID, - const TemplateTypeParmType *Replaced, + static void Profile(llvm::FoldingSetNodeID &ID, const Decl *AssociatedDecl, + unsigned Index, bool Final, const TemplateArgument &ArgPack); static bool classof(const Type *T) { @@ -4946,29 +5418,29 @@ public: /// type-dependent, there is no deduced type and the type is canonical. In /// the latter case, it is also a dependent type. class DeducedType : public Type { + QualType DeducedAsType; + protected: DeducedType(TypeClass TC, QualType DeducedAsType, - TypeDependence ExtraDependence) - : Type(TC, - // FIXME: Retain the sugared deduced type? - DeducedAsType.isNull() ? QualType(this, 0) - : DeducedAsType.getCanonicalType(), + TypeDependence ExtraDependence, QualType Canon) + : Type(TC, Canon, ExtraDependence | (DeducedAsType.isNull() ? TypeDependence::None : DeducedAsType->getDependence() & - ~TypeDependence::VariablyModified)) {} + ~TypeDependence::VariablyModified)), + DeducedAsType(DeducedAsType) {} public: - bool isSugared() const { return !isCanonicalUnqualified(); } - QualType desugar() const { return getCanonicalTypeInternal(); } - - /// Get the type deduced for this placeholder type, or null if it's - /// either not been deduced or was deduced to a dependent type. - QualType getDeducedType() const { - return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType(); + bool isSugared() const { return !DeducedAsType.isNull(); } + QualType desugar() const { + return isSugared() ? DeducedAsType : QualType(this, 0); } + + /// Get the type deduced for this placeholder type, or null if it + /// has not been deduced. + QualType getDeducedType() const { return DeducedAsType; } bool isDeduced() const { - return !isCanonicalUnqualified() || isDependentType(); + return !DeducedAsType.isNull() || isDependentType(); } static bool classof(const Type *T) { @@ -4979,38 +5451,19 @@ public: /// Represents a C++11 auto or C++14 decltype(auto) type, possibly constrained /// by a type-constraint. -class alignas(8) AutoType : public DeducedType, public llvm::FoldingSetNode { +class AutoType : public DeducedType, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these ConceptDecl *TypeConstraintConcept; AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword, - TypeDependence ExtraDependence, ConceptDecl *CD, + TypeDependence ExtraDependence, QualType Canon, ConceptDecl *CD, ArrayRef<TemplateArgument> TypeConstraintArgs); - const TemplateArgument *getArgBuffer() const { - return reinterpret_cast<const TemplateArgument*>(this+1); - } - - TemplateArgument *getArgBuffer() { - return reinterpret_cast<TemplateArgument*>(this+1); - } - public: - /// Retrieve the template arguments. - const TemplateArgument *getArgs() const { - return getArgBuffer(); - } - - /// Retrieve the number of template arguments. - unsigned getNumArgs() const { - return AutoTypeBits.NumArgs; - } - - const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h - ArrayRef<TemplateArgument> getTypeConstraintArguments() const { - return {getArgs(), getNumArgs()}; + return {reinterpret_cast<const TemplateArgument *>(this + 1), + AutoTypeBits.NumArgs}; } ConceptDecl *getTypeConstraintConcept() const { @@ -5025,15 +5478,15 @@ public: return getKeyword() == AutoTypeKeyword::DecltypeAuto; } - AutoTypeKeyword getKeyword() const { - return (AutoTypeKeyword)AutoTypeBits.Keyword; + bool isGNUAutoType() const { + return getKeyword() == AutoTypeKeyword::GNUAutoType; } - void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { - Profile(ID, Context, getDeducedType(), getKeyword(), isDependentType(), - getTypeConstraintConcept(), getTypeConstraintArguments()); + AutoTypeKeyword getKeyword() const { + return (AutoTypeKeyword)AutoTypeBits.Keyword; } + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context); static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, QualType Deduced, AutoTypeKeyword Keyword, bool IsDependent, ConceptDecl *CD, @@ -5059,7 +5512,9 @@ class DeducedTemplateSpecializationType : public DeducedType, toTypeDependence(Template.getDependence()) | (IsDeducedAsDependent ? TypeDependence::DependentInstantiation - : TypeDependence::None)), + : TypeDependence::None), + DeducedAsType.isNull() ? QualType(this, 0) + : DeducedAsType.getCanonicalType()), Template(Template) {} public: @@ -5073,8 +5528,10 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Template, QualType Deduced, bool IsDependent) { Template.Profile(ID); - ID.AddPointer(Deduced.getAsOpaquePtr()); - ID.AddBoolean(IsDependent); + QualType CanonicalType = + Deduced.isNull() ? Deduced : Deduced.getCanonicalType(); + ID.AddPointer(CanonicalType.getAsOpaquePtr()); + ID.AddBoolean(IsDependent || Template.isDependent()); } static bool classof(const Type *T) { @@ -5102,9 +5559,7 @@ public: /// TemplateArguments, followed by a QualType representing the /// non-canonical aliased type when the template is a type alias /// template. -class alignas(8) TemplateSpecializationType - : public Type, - public llvm::FoldingSetNode { +class TemplateSpecializationType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these /// The name of the template being specialized. This is @@ -5167,35 +5622,14 @@ public: /// Get the aliased type, if this is a specialization of a type alias /// template. - QualType getAliasedType() const { - assert(isTypeAlias() && "not a type alias template specialization"); - return *reinterpret_cast<const QualType*>(end()); - } - - using iterator = const TemplateArgument *; - - iterator begin() const { return getArgs(); } - iterator end() const; // defined inline in TemplateBase.h + QualType getAliasedType() const; /// Retrieve the name of the template that we are specializing. TemplateName getTemplateName() const { return Template; } - /// Retrieve the template arguments. - const TemplateArgument *getArgs() const { - return reinterpret_cast<const TemplateArgument *>(this + 1); - } - - /// Retrieve the number of template arguments. - unsigned getNumArgs() const { - return TemplateSpecializationTypeBits.NumArgs; - } - - /// Retrieve a specific template argument as a type. - /// \pre \c isArgType(Arg) - const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h - ArrayRef<TemplateArgument> template_arguments() const { - return {getArgs(), getNumArgs()}; + return {reinterpret_cast<const TemplateArgument *>(this + 1), + TemplateSpecializationTypeBits.NumArgs}; } bool isSugared() const { @@ -5206,12 +5640,7 @@ public: return isTypeAlias() ? getAliasedType() : getCanonicalTypeInternal(); } - void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { - Profile(ID, Template, template_arguments(), Ctx); - if (isTypeAlias()) - getAliasedType().Profile(ID); - } - + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx); static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, ArrayRef<TemplateArgument> Args, const ASTContext &Context); @@ -5238,6 +5667,13 @@ void printTemplateArgumentList(raw_ostream &OS, const PrintingPolicy &Policy, const TemplateParameterList *TPL = nullptr); +/// Make a best-effort determination of whether the type T can be produced by +/// substituting Args into the default argument of Param. +bool isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg, + const NamedDecl *Param, + ArrayRef<TemplateArgument> Args, + unsigned Depth); + /// The injected class name of a C++ class template or class /// template partial specialization. Used to record that a type was /// spelled with a bare identifier rather than as a template-id; the @@ -5306,48 +5742,48 @@ public: } }; -/// The kind of a tag type. -enum TagTypeKind { - /// The "struct" keyword. - TTK_Struct, - - /// The "__interface" keyword. - TTK_Interface, - - /// The "union" keyword. - TTK_Union, - - /// The "class" keyword. - TTK_Class, - - /// The "enum" keyword. - TTK_Enum -}; - /// The elaboration keyword that precedes a qualified type name or /// introduces an elaborated-type-specifier. -enum ElaboratedTypeKeyword { +enum class ElaboratedTypeKeyword { /// The "struct" keyword introduces the elaborated-type-specifier. - ETK_Struct, + Struct, /// The "__interface" keyword introduces the elaborated-type-specifier. - ETK_Interface, + Interface, /// The "union" keyword introduces the elaborated-type-specifier. - ETK_Union, + Union, /// The "class" keyword introduces the elaborated-type-specifier. - ETK_Class, + Class, /// The "enum" keyword introduces the elaborated-type-specifier. - ETK_Enum, + Enum, /// The "typename" keyword precedes the qualified type name, e.g., /// \c typename T::type. - ETK_Typename, + Typename, /// No keyword precedes the qualified type name. - ETK_None + None +}; + +/// The kind of a tag type. +enum class TagTypeKind { + /// The "struct" keyword. + Struct, + + /// The "__interface" keyword. + Interface, + + /// The "union" keyword. + Union, + + /// The "class" keyword. + Class, + + /// The "enum" keyword. + Enum }; /// A helper class for Type nodes having an ElaboratedTypeKeyword. @@ -5359,7 +5795,7 @@ protected: TypeWithKeyword(ElaboratedTypeKeyword Keyword, TypeClass tc, QualType Canonical, TypeDependence Dependence) : Type(tc, Canonical, Dependence) { - TypeWithKeywordBits.Keyword = Keyword; + TypeWithKeywordBits.Keyword = llvm::to_underlying(Keyword); } public: @@ -5436,9 +5872,6 @@ class ElaboratedType final ElaboratedTypeBits.HasOwnedTagDecl = true; *getTrailingObjects<TagDecl *>() = OwnedTagDecl; } - assert(!(Keyword == ETK_None && NNS == nullptr) && - "ElaboratedType cannot have elaborated type keyword " - "and name qualifier both null."); } public: @@ -5468,7 +5901,7 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType, TagDecl *OwnedTagDecl) { - ID.AddInteger(Keyword); + ID.AddInteger(llvm::to_underlying(Keyword)); ID.AddPointer(NNS); NamedType.Profile(ID); ID.AddPointer(OwnedTagDecl); @@ -5527,7 +5960,7 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name) { - ID.AddInteger(Keyword); + ID.AddInteger(llvm::to_underlying(Keyword)); ID.AddPointer(NNS); ID.AddPointer(Name); } @@ -5540,9 +5973,8 @@ public: /// Represents a template specialization type whose template cannot be /// resolved, e.g. /// A<T>::template B<T> -class alignas(8) DependentTemplateSpecializationType - : public TypeWithKeyword, - public llvm::FoldingSetNode { +class DependentTemplateSpecializationType : public TypeWithKeyword, + public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these /// The nested name specifier containing the qualifier. @@ -5557,44 +5989,20 @@ class alignas(8) DependentTemplateSpecializationType ArrayRef<TemplateArgument> Args, QualType Canon); - const TemplateArgument *getArgBuffer() const { - return reinterpret_cast<const TemplateArgument*>(this+1); - } - - TemplateArgument *getArgBuffer() { - return reinterpret_cast<TemplateArgument*>(this+1); - } - public: NestedNameSpecifier *getQualifier() const { return NNS; } const IdentifierInfo *getIdentifier() const { return Name; } - /// Retrieve the template arguments. - const TemplateArgument *getArgs() const { - return getArgBuffer(); - } - - /// Retrieve the number of template arguments. - unsigned getNumArgs() const { - return DependentTemplateSpecializationTypeBits.NumArgs; - } - - const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h - ArrayRef<TemplateArgument> template_arguments() const { - return {getArgs(), getNumArgs()}; + return {reinterpret_cast<const TemplateArgument *>(this + 1), + DependentTemplateSpecializationTypeBits.NumArgs}; } - using iterator = const TemplateArgument *; - - iterator begin() const { return getArgs(); } - iterator end() const; // inline in TemplateBase.h - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { - Profile(ID, Context, getKeyword(), NNS, Name, {getArgs(), getNumArgs()}); + Profile(ID, Context, getKeyword(), NNS, Name, template_arguments()); } static void Profile(llvm::FoldingSetNodeID &ID, @@ -5638,7 +6046,7 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode { QualType Pattern; PackExpansionType(QualType Pattern, QualType Canon, - Optional<unsigned> NumExpansions) + std::optional<unsigned> NumExpansions) : Type(PackExpansion, Canon, (Pattern->getDependence() | TypeDependence::Dependent | TypeDependence::Instantiation) & @@ -5656,10 +6064,10 @@ public: /// Retrieve the number of expansions that this pack expansion will /// generate, if known. - Optional<unsigned> getNumExpansions() const { + std::optional<unsigned> getNumExpansions() const { if (PackExpansionTypeBits.NumExpansions) return PackExpansionTypeBits.NumExpansions - 1; - return None; + return std::nullopt; } bool isSugared() const { return false; } @@ -5670,9 +6078,9 @@ public: } static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern, - Optional<unsigned> NumExpansions) { + std::optional<unsigned> NumExpansions) { ID.AddPointer(Pattern.getAsOpaquePtr()); - ID.AddBoolean(NumExpansions.hasValue()); + ID.AddBoolean(NumExpansions.has_value()); if (NumExpansions) ID.AddInteger(*NumExpansions); } @@ -5927,8 +6335,7 @@ public: /// Retrieve the type arguments of this object type as they were /// written. ArrayRef<QualType> getTypeArgsAsWritten() const { - return llvm::makeArrayRef(getTypeArgStorage(), - ObjCObjectTypeBits.NumTypeArgs); + return llvm::ArrayRef(getTypeArgStorage(), ObjCObjectTypeBits.NumTypeArgs); } /// Whether this is a "__kindof" type as written. @@ -6018,10 +6425,9 @@ inline ObjCProtocolDecl **ObjCTypeParamType::getProtocolStorageImpl() { class ObjCInterfaceType : public ObjCObjectType { friend class ASTContext; // ASTContext creates these. friend class ASTReader; - friend class ObjCInterfaceDecl; template <class T> friend class serialization::AbstractTypeReader; - mutable ObjCInterfaceDecl *Decl; + ObjCInterfaceDecl *Decl; ObjCInterfaceType(const ObjCInterfaceDecl *D) : ObjCObjectType(Nonce_ObjCInterface), @@ -6029,7 +6435,7 @@ class ObjCInterfaceType : public ObjCObjectType { public: /// Get the declaration of this interface. - ObjCInterfaceDecl *getDecl() const { return Decl; } + ObjCInterfaceDecl *getDecl() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -6306,13 +6712,14 @@ public: }; /// A fixed int type of a specified bitwidth. -class ExtIntType final : public Type, public llvm::FoldingSetNode { +class BitIntType final : public Type, public llvm::FoldingSetNode { friend class ASTContext; + LLVM_PREFERRED_TYPE(bool) unsigned IsUnsigned : 1; unsigned NumBits : 24; protected: - ExtIntType(bool isUnsigned, unsigned NumBits); + BitIntType(bool isUnsigned, unsigned NumBits); public: bool isUnsigned() const { return IsUnsigned; } @@ -6322,7 +6729,7 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, isUnsigned(), getNumBits()); } @@ -6332,17 +6739,15 @@ public: ID.AddInteger(NumBits); } - static bool classof(const Type *T) { return T->getTypeClass() == ExtInt; } + static bool classof(const Type *T) { return T->getTypeClass() == BitInt; } }; -class DependentExtIntType final : public Type, public llvm::FoldingSetNode { +class DependentBitIntType final : public Type, public llvm::FoldingSetNode { friend class ASTContext; - const ASTContext &Context; llvm::PointerIntPair<Expr*, 1, bool> ExprAndUnsigned; protected: - DependentExtIntType(const ASTContext &Context, bool IsUnsigned, - Expr *NumBits); + DependentBitIntType(bool IsUnsigned, Expr *NumBits); public: bool isUnsigned() const; @@ -6352,14 +6757,14 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, isUnsigned(), getNumBitsExpr()); } static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool IsUnsigned, Expr *NumBitsExpr); static bool classof(const Type *T) { - return T->getTypeClass() == DependentExtInt; + return T->getTypeClass() == DependentBitInt; } }; @@ -6402,7 +6807,7 @@ class alignas(8) TypeSourceInfo { QualType Ty; - TypeSourceInfo(QualType ty) : Ty(ty) {} + TypeSourceInfo(QualType ty, size_t DataSize); // implemented in TypeLoc.h public: /// Return the type wrapped by this type source info. @@ -6432,6 +6837,19 @@ inline const Type *QualType::getTypePtrOrNull() const { return (isNull() ? nullptr : getCommonPtr()->BaseType); } +inline bool QualType::isReferenceable() const { + // C++ [defns.referenceable] + // type that is either an object type, a function type that does not have + // cv-qualifiers or a ref-qualifier, or a reference type. + const Type &Self = **this; + if (Self.isObjectType() || Self.isReferenceType()) + return true; + if (const auto *F = Self.getAs<FunctionProtoType>()) + return F->getMethodQuals().empty() && F->getRefQualifier() == RQ_None; + + return false; +} + inline SplitQualType QualType::split() const { if (!hasLocalNonFastQualifiers()) return SplitQualType(getTypePtrUnsafe(), @@ -6530,15 +6948,6 @@ inline void QualType::removeLocalVolatile() { removeLocalFastQualifiers(Qualifiers::Volatile); } -inline void QualType::removeLocalCVRQualifiers(unsigned Mask) { - assert(!(Mask & ~Qualifiers::CVRMask) && "mask has non-CVR bits"); - static_assert((int)Qualifiers::CVRMask == (int)Qualifiers::FastMask, - "Fast bits differ from CVR bits!"); - - // Fast path: we don't need to touch the slow qualifiers. - removeLocalFastQualifiers(Mask); -} - /// Check if this type has any address space qualifier. inline bool QualType::hasAddressSpace() const { return getQualifiers().hasAddressSpace(); @@ -6782,6 +7191,12 @@ inline bool Type::isExtVectorType() const { return isa<ExtVectorType>(CanonicalType); } +inline bool Type::isExtVectorBoolType() const { + if (!isExtVectorType()) + return false; + return cast<ExtVectorType>(CanonicalType)->getElementType()->isBooleanType(); +} + inline bool Type::isMatrixType() const { return isa<MatrixType>(CanonicalType); } @@ -6890,8 +7305,8 @@ inline bool Type::isPipeType() const { return isa<PipeType>(CanonicalType); } -inline bool Type::isExtIntType() const { - return isa<ExtIntType>(CanonicalType); +inline bool Type::isBitIntType() const { + return isa<BitIntType>(CanonicalType); } #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ @@ -6976,6 +7391,10 @@ inline bool Type::isFloat128Type() const { return isSpecificBuiltinType(BuiltinType::Float128); } +inline bool Type::isIbm128Type() const { + return isSpecificBuiltinType(BuiltinType::Ibm128); +} + inline bool Type::isNullPtrType() const { return isSpecificBuiltinType(BuiltinType::NullPtr); } @@ -6993,7 +7412,7 @@ inline bool Type::isIntegerType() const { return IsEnumDeclComplete(ET->getDecl()) && !IsEnumDeclScoped(ET->getDecl()); } - return isExtIntType(); + return isBitIntType(); } inline bool Type::isFixedPointType() const { @@ -7051,7 +7470,7 @@ inline bool Type::isScalarType() const { isa<MemberPointerType>(CanonicalType) || isa<ComplexType>(CanonicalType) || isa<ObjCObjectPointerType>(CanonicalType) || - isExtIntType(); + isBitIntType(); } inline bool Type::isIntegralOrEnumerationType() const { @@ -7064,7 +7483,7 @@ inline bool Type::isIntegralOrEnumerationType() const { if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) return IsEnumDeclComplete(ET->getDecl()); - return isExtIntType(); + return isBitIntType(); } inline bool Type::isBooleanType() const { @@ -7126,7 +7545,7 @@ inline const Type *Type::getPointeeOrArrayElementType() const { /// spaces into a diagnostic with <<. inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD, LangAS AS) { - PD.AddTaggedVal(static_cast<std::underlying_type_t<LangAS>>(AS), + PD.AddTaggedVal(llvm::to_underlying(AS), DiagnosticsEngine::ArgumentKind::ak_addrspace); return PD; } @@ -7144,7 +7563,7 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD, /// into a diagnostic with <<. inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD, QualType T) { - PD.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()), + PD.AddTaggedVal(reinterpret_cast<uint64_t>(T.getAsOpaquePtr()), DiagnosticsEngine::ak_qualtype); return PD; } @@ -7191,6 +7610,8 @@ template <typename T> const T *Type::getAsAdjusted() const { while (Ty) { if (const auto *A = dyn_cast<AttributedType>(Ty)) Ty = A->getModifiedType().getTypePtr(); + else if (const auto *A = dyn_cast<BTFTagAttributedType>(Ty)) + Ty = A->getWrappedType().getTypePtr(); else if (const auto *E = dyn_cast<ElaboratedType>(Ty)) Ty = E->desugar().getTypePtr(); else if (const auto *P = dyn_cast<ParenType>(Ty)) diff --git a/contrib/llvm-project/clang/include/clang/AST/TypeLoc.h b/contrib/llvm-project/clang/include/clang/AST/TypeLoc.h index 65e95d52c303..471deb14aba5 100644 --- a/contrib/llvm-project/clang/include/clang/AST/TypeLoc.h +++ b/contrib/llvm-project/clang/include/clang/AST/TypeLoc.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_TYPELOC_H #define LLVM_CLANG_AST_TYPELOC_H +#include "clang/AST/ASTConcept.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateBase.h" @@ -240,6 +241,11 @@ private: static SourceRange getLocalSourceRangeImpl(TypeLoc TL); }; +inline TypeSourceInfo::TypeSourceInfo(QualType ty, size_t DataSize) : Ty(ty) { + // Init data attached to the object. See getTypeLoc. + memset(static_cast<void *>(this + 1), 0, DataSize); +} + /// Return the TypeLoc for a type source info. inline TypeLoc TypeSourceInfo::getTypeLoc() const { // TODO: is this alignment already sufficient? @@ -430,7 +436,7 @@ protected: unsigned size = sizeof(LocalData); unsigned extraAlign = asDerived()->getExtraLocalDataAlignment(); size = llvm::alignTo(size, extraAlign); - return reinterpret_cast<char*>(Base::Data) + size; + return reinterpret_cast<char *>(Base::Data) + size; } void *getNonLocalData() const { @@ -581,10 +587,9 @@ public: bool needsExtraLocalData() const { BuiltinType::Kind bk = getTypePtr()->getKind(); - return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128) - || (bk >= BuiltinType::Short && bk <= BuiltinType::Float128) - || bk == BuiltinType::UChar - || bk == BuiltinType::SChar; + return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128) || + (bk >= BuiltinType::Short && bk <= BuiltinType::Ibm128) || + bk == BuiltinType::UChar || bk == BuiltinType::SChar; } unsigned getExtraLocalDataSize() const { @@ -666,6 +671,16 @@ public: } }; +/// Wrapper for source info for types used via transparent aliases. +class UsingTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + UsingTypeLoc, UsingType> { +public: + QualType getUnderlyingType() const { + return getTypePtr()->getUnderlyingType(); + } + UsingShadowDecl *getFoundDecl() const { return getTypePtr()->getFoundDecl(); } +}; + /// Wrapper for source info for typedefs. class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, TypedefTypeLoc, @@ -805,7 +820,7 @@ public: } ArrayRef<SourceLocation> getProtocolLocs() const { - return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols()); + return llvm::ArrayRef(getProtocolLocArray(), getNumProtocols()); } void initializeLocal(ASTContext &Context, SourceLocation Loc); @@ -892,6 +907,29 @@ public: } }; +struct BTFTagAttributedLocInfo {}; // Nothing. + +/// Type source information for an btf_tag attributed type. +class BTFTagAttributedTypeLoc + : public ConcreteTypeLoc<UnqualTypeLoc, BTFTagAttributedTypeLoc, + BTFTagAttributedType, BTFTagAttributedLocInfo> { +public: + TypeLoc getWrappedLoc() const { return getInnerTypeLoc(); } + + /// The btf_type_tag attribute. + const BTFTypeTagAttr *getAttr() const { return getTypePtr()->getAttr(); } + + template <typename T> T *getAttrAs() { + return dyn_cast_or_null<T>(getAttr()); + } + + SourceRange getLocalSourceRange() const; + + void initializeLocal(ASTContext &Context, SourceLocation loc) {} + + QualType getInnerType() const { return getTypePtr()->getWrappedType(); } +}; + struct ObjCObjectTypeLocInfo { SourceLocation TypeArgsLAngleLoc; SourceLocation TypeArgsRAngleLoc; @@ -988,7 +1026,7 @@ public: ArrayRef<SourceLocation> getProtocolLocs() const { - return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols()); + return llvm::ArrayRef(getProtocolLocArray(), getNumProtocols()); } bool hasBaseTypeAsWritten() const { @@ -1415,7 +1453,7 @@ public: } ArrayRef<ParmVarDecl *> getParams() const { - return llvm::makeArrayRef(getParmArray(), getNumParams()); + return llvm::ArrayRef(getParmArray(), getNumParams()); } // ParmVarDecls* are stored after Info, one for each parameter. @@ -1602,7 +1640,7 @@ public: } unsigned getNumArgs() const { - return getTypePtr()->getNumArgs(); + return getTypePtr()->template_arguments().size(); } void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { @@ -1614,7 +1652,8 @@ public: } TemplateArgumentLoc getArgLoc(unsigned i) const { - return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i)); + return TemplateArgumentLoc(getTypePtr()->template_arguments()[i], + getArgLocInfo(i)); } SourceLocation getTemplateNameLoc() const { @@ -1649,12 +1688,12 @@ public: setTemplateNameLoc(Loc); setLAngleLoc(Loc); setRAngleLoc(Loc); - initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(), + initializeArgLocs(Context, getTypePtr()->template_arguments(), getArgInfos(), Loc); } - static void initializeArgLocs(ASTContext &Context, unsigned NumArgs, - const TemplateArgument *Args, + static void initializeArgLocs(ASTContext &Context, + ArrayRef<TemplateArgument> Args, TemplateArgumentLocInfo *ArgInfos, SourceLocation Loc); @@ -1902,7 +1941,7 @@ struct TypeOfExprTypeLocInfo : public TypeofLocInfo { }; struct TypeOfTypeLocInfo : public TypeofLocInfo { - TypeSourceInfo* UnderlyingTInfo; + TypeSourceInfo *UnmodifiedTInfo; }; template <class Derived, class TypeClass, class LocalData = TypeofLocInfo> @@ -1970,27 +2009,50 @@ public: class TypeOfTypeLoc : public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> { public: - QualType getUnderlyingType() const { - return this->getTypePtr()->getUnderlyingType(); + QualType getUnmodifiedType() const { + return this->getTypePtr()->getUnmodifiedType(); } - TypeSourceInfo* getUnderlyingTInfo() const { - return this->getLocalData()->UnderlyingTInfo; + TypeSourceInfo *getUnmodifiedTInfo() const { + return this->getLocalData()->UnmodifiedTInfo; } - void setUnderlyingTInfo(TypeSourceInfo* TI) const { - this->getLocalData()->UnderlyingTInfo = TI; + void setUnmodifiedTInfo(TypeSourceInfo *TI) const { + this->getLocalData()->UnmodifiedTInfo = TI; } void initializeLocal(ASTContext &Context, SourceLocation Loc); }; -// FIXME: location of the 'decltype' and parens. -class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - DecltypeTypeLoc, - DecltypeType> { +// decltype(expression) abc; +// ~~~~~~~~ DecltypeLoc +// ~ RParenLoc +// FIXME: add LParenLoc, it is tricky to support due to the limitation of +// annotated-decltype token. +struct DecltypeTypeLocInfo { + SourceLocation DecltypeLoc; + SourceLocation RParenLoc; +}; +class DecltypeTypeLoc + : public ConcreteTypeLoc<UnqualTypeLoc, DecltypeTypeLoc, DecltypeType, + DecltypeTypeLocInfo> { public: Expr *getUnderlyingExpr() const { return getTypePtr()->getUnderlyingExpr(); } + + SourceLocation getDecltypeLoc() const { return getLocalData()->DecltypeLoc; } + void setDecltypeLoc(SourceLocation Loc) { getLocalData()->DecltypeLoc = Loc; } + + SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; } + void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; } + + SourceRange getLocalSourceRange() const { + return SourceRange(getDecltypeLoc(), getRParenLoc()); + } + + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + setDecltypeLoc(Loc); + setRParenLoc(Loc); + } }; struct UnaryTransformTypeLocInfo { @@ -2043,12 +2105,10 @@ class DeducedTypeLoc DeducedType> {}; struct AutoTypeLocInfo : TypeSpecLocInfo { - NestedNameSpecifierLoc NestedNameSpec; - SourceLocation TemplateKWLoc; - SourceLocation ConceptNameLoc; - NamedDecl *FoundDecl; - SourceLocation LAngleLoc; - SourceLocation RAngleLoc; + // For decltype(auto). + SourceLocation RParenLoc; + + ConceptReference *CR = nullptr; }; class AutoTypeLoc @@ -2061,96 +2121,95 @@ public: return getTypePtr()->getKeyword(); } + bool isDecltypeAuto() const { return getTypePtr()->isDecltypeAuto(); } + SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; } + void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; } + bool isConstrained() const { return getTypePtr()->isConstrained(); } - const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { - return getLocalData()->NestedNameSpec; - } + void setConceptReference(ConceptReference *CR) { getLocalData()->CR = CR; } - void setNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { - getLocalData()->NestedNameSpec = NNS; - } + ConceptReference *getConceptReference() const { return getLocalData()->CR; } - SourceLocation getTemplateKWLoc() const { - return getLocalData()->TemplateKWLoc; + // FIXME: Several of the following functions can be removed. Instead the + // caller can directly work with the ConceptReference. + const NestedNameSpecifierLoc getNestedNameSpecifierLoc() const { + if (const auto *CR = getConceptReference()) + return CR->getNestedNameSpecifierLoc(); + return NestedNameSpecifierLoc(); } - void setTemplateKWLoc(SourceLocation Loc) { - getLocalData()->TemplateKWLoc = Loc; + SourceLocation getTemplateKWLoc() const { + if (const auto *CR = getConceptReference()) + return CR->getTemplateKWLoc(); + return SourceLocation(); } SourceLocation getConceptNameLoc() const { - return getLocalData()->ConceptNameLoc; - } - - void setConceptNameLoc(SourceLocation Loc) { - getLocalData()->ConceptNameLoc = Loc; + if (const auto *CR = getConceptReference()) + return CR->getConceptNameLoc(); + return SourceLocation(); } NamedDecl *getFoundDecl() const { - return getLocalData()->FoundDecl; - } - - void setFoundDecl(NamedDecl *D) { - getLocalData()->FoundDecl = D; + if (const auto *CR = getConceptReference()) + return CR->getFoundDecl(); + return nullptr; } ConceptDecl *getNamedConcept() const { - return getTypePtr()->getTypeConstraintConcept(); + if (const auto *CR = getConceptReference()) + return CR->getNamedConcept(); + return nullptr; } - DeclarationNameInfo getConceptNameInfo() const; + DeclarationNameInfo getConceptNameInfo() const { + return getConceptReference()->getConceptNameInfo(); + } bool hasExplicitTemplateArgs() const { - return getLocalData()->LAngleLoc.isValid(); + return (getConceptReference() && + getConceptReference()->getTemplateArgsAsWritten() && + getConceptReference() + ->getTemplateArgsAsWritten() + ->getLAngleLoc() + .isValid()); } SourceLocation getLAngleLoc() const { - return this->getLocalData()->LAngleLoc; - } - - void setLAngleLoc(SourceLocation Loc) { - this->getLocalData()->LAngleLoc = Loc; + if (const auto *CR = getConceptReference()) + if (const auto *TAAW = CR->getTemplateArgsAsWritten()) + return TAAW->getLAngleLoc(); + return SourceLocation(); } SourceLocation getRAngleLoc() const { - return this->getLocalData()->RAngleLoc; - } - - void setRAngleLoc(SourceLocation Loc) { - this->getLocalData()->RAngleLoc = Loc; + if (const auto *CR = getConceptReference()) + if (const auto *TAAW = CR->getTemplateArgsAsWritten()) + return TAAW->getRAngleLoc(); + return SourceLocation(); } unsigned getNumArgs() const { - return getTypePtr()->getNumArgs(); - } - - void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { - getArgInfos()[i] = AI; - } - - TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { - return getArgInfos()[i]; + return getTypePtr()->getTypeConstraintArguments().size(); } TemplateArgumentLoc getArgLoc(unsigned i) const { - return TemplateArgumentLoc(getTypePtr()->getTypeConstraintArguments()[i], - getArgLocInfo(i)); + const auto *CR = getConceptReference(); + assert(CR && "No ConceptReference"); + return CR->getTemplateArgsAsWritten()->getTemplateArgs()[i]; } SourceRange getLocalSourceRange() const { - return{ - isConstrained() - ? (getNestedNameSpecifierLoc() - ? getNestedNameSpecifierLoc().getBeginLoc() - : (getTemplateKWLoc().isValid() - ? getTemplateKWLoc() - : getConceptNameLoc())) - : getNameLoc(), - getNameLoc() - }; + return {isConstrained() + ? (getNestedNameSpecifierLoc() + ? getNestedNameSpecifierLoc().getBeginLoc() + : (getTemplateKWLoc().isValid() ? getTemplateKWLoc() + : getConceptNameLoc())) + : getNameLoc(), + isDecltypeAuto() ? getRParenLoc() : getNameLoc()}; } void copy(AutoTypeLoc Loc) { @@ -2160,19 +2219,6 @@ public: } void initializeLocal(ASTContext &Context, SourceLocation Loc); - - unsigned getExtraLocalDataSize() const { - return getNumArgs() * sizeof(TemplateArgumentLocInfo); - } - - unsigned getExtraLocalDataAlignment() const { - return alignof(TemplateArgumentLocInfo); - } - -private: - TemplateArgumentLocInfo *getArgInfos() const { - return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData()); - } }; class DeducedTemplateSpecializationTypeLoc @@ -2202,22 +2248,31 @@ class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, ElaboratedLocInfo> { public: SourceLocation getElaboratedKeywordLoc() const { - return this->getLocalData()->ElaboratedKWLoc; + return !isEmpty() ? getLocalData()->ElaboratedKWLoc : SourceLocation(); } void setElaboratedKeywordLoc(SourceLocation Loc) { - this->getLocalData()->ElaboratedKWLoc = Loc; + if (isEmpty()) { + assert(Loc.isInvalid()); + return; + } + getLocalData()->ElaboratedKWLoc = Loc; } NestedNameSpecifierLoc getQualifierLoc() const { - return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), - getLocalData()->QualifierData); + return !isEmpty() ? NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + getLocalData()->QualifierData) + : NestedNameSpecifierLoc(); } void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { - assert(QualifierLoc.getNestedNameSpecifier() - == getTypePtr()->getQualifier() && + assert(QualifierLoc.getNestedNameSpecifier() == + getTypePtr()->getQualifier() && "Inconsistent nested-name-specifier pointer"); + if (isEmpty()) { + assert(!QualifierLoc.hasQualifier()); + return; + } getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } @@ -2234,12 +2289,24 @@ public: void initializeLocal(ASTContext &Context, SourceLocation Loc); - TypeLoc getNamedTypeLoc() const { - return getInnerTypeLoc(); + TypeLoc getNamedTypeLoc() const { return getInnerTypeLoc(); } + + QualType getInnerType() const { return getTypePtr()->getNamedType(); } + + bool isEmpty() const { + return getTypePtr()->getKeyword() == ElaboratedTypeKeyword::None && + !getTypePtr()->getQualifier(); } - QualType getInnerType() const { - return getTypePtr()->getNamedType(); + unsigned getLocalDataAlignment() const { + // FIXME: We want to return 1 here in the empty case, but + // there are bugs in how alignment is handled in TypeLocs + // that prevent this from working. + return ConcreteTypeLoc::getLocalDataAlignment(); + } + + unsigned getLocalDataSize() const { + return !isEmpty() ? ConcreteTypeLoc::getLocalDataSize() : 0; } void copy(ElaboratedTypeLoc Loc) { @@ -2382,7 +2449,7 @@ public: } unsigned getNumArgs() const { - return getTypePtr()->getNumArgs(); + return getTypePtr()->template_arguments().size(); } void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { @@ -2394,7 +2461,8 @@ public: } TemplateArgumentLoc getArgLoc(unsigned i) const { - return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i)); + return TemplateArgumentLoc(getTypePtr()->template_arguments()[i], + getArgLocInfo(i)); } SourceRange getLocalSourceRange() const { @@ -2551,6 +2619,8 @@ inline T TypeLoc::getAsAdjusted() const { Cur = PTL.getInnerLoc(); else if (auto ATL = Cur.getAs<AttributedTypeLoc>()) Cur = ATL.getModifiedLoc(); + else if (auto ATL = Cur.getAs<BTFTagAttributedTypeLoc>()) + Cur = ATL.getWrappedLoc(); else if (auto ETL = Cur.getAs<ElaboratedTypeLoc>()) Cur = ETL.getNamedTypeLoc(); else if (auto ATL = Cur.getAs<AdjustedTypeLoc>()) @@ -2562,12 +2632,28 @@ inline T TypeLoc::getAsAdjusted() const { } return Cur.getAs<T>(); } -class ExtIntTypeLoc final - : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, ExtIntTypeLoc, - ExtIntType> {}; -class DependentExtIntTypeLoc final - : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DependentExtIntTypeLoc, - DependentExtIntType> {}; +class BitIntTypeLoc final + : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, BitIntTypeLoc, + BitIntType> {}; +class DependentBitIntTypeLoc final + : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DependentBitIntTypeLoc, + DependentBitIntType> {}; + +class ObjCProtocolLoc { + ObjCProtocolDecl *Protocol = nullptr; + SourceLocation Loc = SourceLocation(); + +public: + ObjCProtocolLoc(ObjCProtocolDecl *protocol, SourceLocation loc) + : Protocol(protocol), Loc(loc) {} + ObjCProtocolDecl *getProtocol() const { return Protocol; } + SourceLocation getLocation() const { return Loc; } + + /// The source range is just the protocol name. + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(Loc, Loc); + } +}; } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/AST/TypeOrdering.h b/contrib/llvm-project/clang/include/clang/AST/TypeOrdering.h index 6630105136f5..8037f98cc965 100644 --- a/contrib/llvm-project/clang/include/clang/AST/TypeOrdering.h +++ b/contrib/llvm-project/clang/include/clang/AST/TypeOrdering.h @@ -34,7 +34,6 @@ struct QualTypeOrdering { } namespace llvm { - template<class> struct DenseMapInfo; template<> struct DenseMapInfo<clang::QualType> { static inline clang::QualType getEmptyKey() { return clang::QualType(); } diff --git a/contrib/llvm-project/clang/include/clang/AST/TypeProperties.td b/contrib/llvm-project/clang/include/clang/AST/TypeProperties.td index 438d5af5a2e2..682c869b0c58 100644 --- a/contrib/llvm-project/clang/include/clang/AST/TypeProperties.td +++ b/contrib/llvm-project/clang/include/clang/AST/TypeProperties.td @@ -11,7 +11,7 @@ include "clang/Basic/TypeNodes.td" let Class = ComplexType in { def : Property<"elementType", QualType> { - let Read = [{ node->getElementType() }]; + let Read = [{ node->getElementType() }]; } def : Creator<[{ return ctx.getComplexType(elementType); }]>; @@ -323,6 +323,9 @@ let Class = FunctionProtoType in { ? node->getExtParameterInfos() : llvm::ArrayRef<FunctionProtoType::ExtParameterInfo>() }]; } + def : Property<"AArch64SMEAttributes", UInt32> { + let Read = [{ node->getAArch64SMEAttributes() }]; + } def : Creator<[{ auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm, @@ -338,6 +341,7 @@ let Class = FunctionProtoType in { epi.ExceptionSpec = exceptionSpecifier; epi.ExtParameterInfos = extParameterInfo.empty() ? nullptr : extParameterInfo.data(); + epi.AArch64SMEAttributes = AArch64SMEAttributes; return ctx.getFunctionType(returnType, parameters, epi); }]>; } @@ -358,7 +362,20 @@ let Class = UnresolvedUsingType in { } def : Creator<[{ - return ctx.getTypeDeclType(cast<UnresolvedUsingTypenameDecl>(declaration)); + return ctx.getUnresolvedUsingType(cast<UnresolvedUsingTypenameDecl>(declaration)); + }]>; +} + +let Class = UsingType in { + def : Property<"foundDeclaration", UsingShadowDeclRef> { + let Read = [{ node->getFoundDecl() }]; + } + def : Property<"underlyingType", QualType> { + let Read = [{ node->getUnderlyingType() }]; + } + + def : Creator<[{ + return ctx.getUsingType(foundDeclaration, underlyingType); }]>; } @@ -366,16 +383,12 @@ let Class = TypedefType in { def : Property<"declaration", DeclRef> { let Read = [{ node->getDecl() }]; } - def : Property<"canonicalType", Optional<QualType>> { - let Read = [{ makeOptionalFromNullable(node->getCanonicalTypeInternal()) }]; + def : Property<"underlyingType", QualType> { + let Read = [{ node->desugar() }]; } def : Creator<[{ - QualType finalCanonicalType = - canonicalType ? ctx.getCanonicalType(*canonicalType) - : QualType(); - return ctx.getTypedefType(cast<TypedefNameDecl>(declaration), - finalCanonicalType); + return ctx.getTypedefType(cast<TypedefNameDecl>(declaration), underlyingType); }]>; } @@ -384,18 +397,26 @@ let Class = TypeOfExprType in { let Read = [{ node->getUnderlyingExpr() }]; } + def : Property<"kind", TypeOfKind> { + let Read = [{ node->getKind() }]; + } + def : Creator<[{ - return ctx.getTypeOfExprType(expression); + return ctx.getTypeOfExprType(expression, kind); }]>; } let Class = TypeOfType in { - def : Property<"underlyingType", QualType> { - let Read = [{ node->getUnderlyingType() }]; + def : Property<"unmodifiedType", QualType> { + let Read = [{ node->getUnmodifiedType() }]; + } + + def : Property<"kind", TypeOfKind> { + let Read = [{ node->getKind() }]; } def : Creator<[{ - return ctx.getTypeOfType(underlyingType); + return ctx.getTypeOfType(unmodifiedType, kind); }]>; } @@ -574,7 +595,7 @@ let Class = ParenType in { def : Creator<[{ return ctx.getParenType(innerType); - }]>; + }]>; } let Class = MacroQualifiedType in { @@ -606,6 +627,19 @@ let Class = AttributedType in { }]>; } +let Class = BTFTagAttributedType in { + def : Property<"attr", BTFTypeTagAttr> { + let Read = [{ node->getAttr() }]; + } + def : Property<"wrappedType", QualType> { + let Read = [{ node->getWrappedType() }]; + } + + def : Creator<[{ + return ctx.getBTFTagAttributedType(attr, wrappedType); + }]>; +} + let Class = DependentAddressSpaceType in { def : Property<"pointeeType", QualType> { let Read = [{ node->getPointeeType() }]; @@ -636,16 +670,16 @@ let Class = TemplateSpecializationType in { def : Property<"underlyingType", Optional<QualType>> { let Read = [{ node->isTypeAlias() - ? llvm::Optional<QualType>(node->getAliasedType()) + ? std::optional<QualType>(node->getAliasedType()) : node->isCanonicalUnqualified() - ? llvm::None - : llvm::Optional<QualType>(node->getCanonicalTypeInternal()) + ? std::nullopt + : std::optional<QualType>(node->getCanonicalTypeInternal()) }]; } def : Creator<[{ QualType result; - if (!underlyingType.hasValue()) { + if (!underlyingType) { result = ctx.getCanonicalTemplateSpecializationType(templateName, templateArguments); } else { @@ -702,18 +736,23 @@ let Class = TemplateTypeParmType in { } let Class = SubstTemplateTypeParmType in { - def : Property<"replacedParameter", QualType> { - let Read = [{ QualType(node->getReplacedParameter(), 0) }]; - } def : Property<"replacementType", QualType> { let Read = [{ node->getReplacementType() }]; } + def : Property<"associatedDecl", DeclRef> { + let Read = [{ node->getAssociatedDecl() }]; + } + def : Property<"Index", UInt32> { + let Read = [{ node->getIndex() }]; + } + def : Property<"PackIndex", Optional<UInt32>> { + let Read = [{ node->getPackIndex() }]; + } + // The call to getCanonicalType here existed in ASTReader.cpp, too. def : Creator<[{ - // The call to getCanonicalType here existed in ASTReader.cpp, too. return ctx.getSubstTemplateTypeParmType( - cast<TemplateTypeParmType>(replacedParameter), - ctx.getCanonicalType(replacementType)); + replacementType, associatedDecl, Index, PackIndex); }]>; } @@ -732,8 +771,14 @@ let Class = PackExpansionType in { } let Class = SubstTemplateTypeParmPackType in { - def : Property<"replacedParameter", QualType> { - let Read = [{ QualType(node->getReplacedParameter(), 0) }]; + def : Property<"associatedDecl", DeclRef> { + let Read = [{ node->getAssociatedDecl() }]; + } + def : Property<"Index", UInt32> { + let Read = [{ node->getIndex() }]; + } + def : Property<"Final", Bool> { + let Read = [{ node->getFinal() }]; } def : Property<"replacementPack", TemplateArgument> { let Read = [{ node->getArgumentPack() }]; @@ -741,8 +786,7 @@ let Class = SubstTemplateTypeParmPackType in { def : Creator<[{ return ctx.getSubstTemplateTypeParmPackType( - cast<TemplateTypeParmType>(replacedParameter), - replacementPack); + associatedDecl, Index, Final, replacementPack); }]>; } @@ -773,6 +817,10 @@ let Class = BuiltinType in { case BuiltinType::ID: return ctx.SINGLETON_ID; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(NAME, ID, SINGLETON_ID) \ + case BuiltinType::ID: return ctx.SINGLETON_ID; +#include "clang/Basic/WebAssemblyReferenceTypes.def" + #define BUILTIN_TYPE(ID, SINGLETON_ID) \ case BuiltinType::ID: return ctx.SINGLETON_ID; #include "clang/AST/BuiltinTypes.def" @@ -794,8 +842,8 @@ let Class = DependentNameType in { def : Property<"underlyingType", Optional<QualType>> { let Read = [{ node->isCanonicalUnqualified() - ? llvm::None - : llvm::Optional<QualType>(node->getCanonicalTypeInternal()) + ? std::nullopt + : std::optional<QualType>(node->getCanonicalTypeInternal()) }]; } @@ -849,7 +897,7 @@ let Class = ObjCInterfaceType in { let Class = ObjCTypeParamType in { def : Property<"declaration", ObjCTypeParamDeclRef> { let Read = [{ node->getDecl() }]; - } + } def : Property<"qualifiers", Array<ObjCProtocolDeclRef>> { let Read = [{ node->getProtocols() }]; } @@ -882,7 +930,7 @@ let Class = PipeType in { }]>; } -let Class = ExtIntType in { +let Class = BitIntType in { def : Property<"isUnsigned", Bool> { let Read = [{ node->isUnsigned() }]; } @@ -891,11 +939,11 @@ let Class = ExtIntType in { } def : Creator<[{ - return ctx.getExtIntType(isUnsigned, numBits); + return ctx.getBitIntType(isUnsigned, numBits); }]>; } -let Class = DependentExtIntType in { +let Class = DependentBitIntType in { def : Property<"isUnsigned", Bool> { let Read = [{ node->isUnsigned() }]; } @@ -903,6 +951,6 @@ let Class = DependentExtIntType in { let Read = [{ node->getNumBitsExpr() }]; } def : Creator<[{ - return ctx.getDependentExtIntType(isUnsigned, numBitsExpr); + return ctx.getDependentBitIntType(isUnsigned, numBitsExpr); }]>; } diff --git a/contrib/llvm-project/clang/include/clang/AST/UnresolvedSet.h b/contrib/llvm-project/clang/include/clang/AST/UnresolvedSet.h index c75aa0785a63..ee31be969b6e 100644 --- a/contrib/llvm-project/clang/include/clang/AST/UnresolvedSet.h +++ b/contrib/llvm-project/clang/include/clang/AST/UnresolvedSet.h @@ -114,14 +114,22 @@ public: I.I->set(New, AS); } - void erase(unsigned I) { decls()[I] = decls().pop_back_val(); } + void erase(unsigned I) { + auto val = decls().pop_back_val(); + if (I < size()) + decls()[I] = val; + } - void erase(iterator I) { *I.I = decls().pop_back_val(); } + void erase(iterator I) { + auto val = decls().pop_back_val(); + if (I != end()) + *I.I = val; + } void setAccess(iterator I, AccessSpecifier AS) { I.I->setAccess(AS); } void clear() { decls().clear(); } - void set_size(unsigned N) { decls().set_size(N); } + void truncate(unsigned N) { decls().truncate(N); } bool empty() const { return decls().empty(); } unsigned size() const { return decls().size(); } diff --git a/contrib/llvm-project/clang/include/clang/AST/VTableBuilder.h b/contrib/llvm-project/clang/include/clang/AST/VTableBuilder.h index e451f3f861b7..fbf6c041a1ec 100644 --- a/contrib/llvm-project/clang/include/clang/AST/VTableBuilder.h +++ b/contrib/llvm-project/clang/include/clang/AST/VTableBuilder.h @@ -279,7 +279,7 @@ public: AddressPointLocation getAddressPoint(BaseSubobject Base) const { assert(AddressPoints.count(Base) && "Did not find address point!"); - return AddressPoints.find(Base)->second; + return AddressPoints.lookup(Base); } const AddressPointsMapTy &getAddressPoints() const { @@ -563,8 +563,6 @@ private: llvm::DenseMap<const CXXRecordDecl *, std::unique_ptr<VirtualBaseInfo>> VBaseInfo; - void enumerateVFPtrs(const CXXRecordDecl *ForClass, VPtrInfoVector &Result); - void computeVTableRelatedInformation(const CXXRecordDecl *RD) override; void dumpMethodLocations(const CXXRecordDecl *RD, |