diff options
Diffstat (limited to 'clang/include/clang/AST/DeclCXX.h')
| -rw-r--r-- | clang/include/clang/AST/DeclCXX.h | 193 |
1 files changed, 164 insertions, 29 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index b716ea453a5a0..2b8d7e879a0aa 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -15,7 +15,6 @@ #ifndef LLVM_CLANG_AST_DECLCXX_H #define LLVM_CLANG_AST_DECLCXX_H -#include "clang/AST/ASTContext.h" #include "clang/AST/ASTUnresolvedSet.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" @@ -40,6 +39,7 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" @@ -53,6 +53,7 @@ namespace clang { +class ASTContext; class ClassTemplateDecl; class ConstructorUsingShadowDecl; class CXXBasePath; @@ -712,6 +713,13 @@ public: } /// \c true if we know for sure that this class has a single, + /// accessible, unambiguous copy assignment operator that is not deleted. + bool hasSimpleCopyAssignment() const { + return !hasUserDeclaredCopyAssignment() && + !data().DefaultedCopyAssignmentIsDeleted; + } + + /// \c true if we know for sure that this class has a single, /// accessible, unambiguous move assignment operator that is not deleted. bool hasSimpleMoveAssignment() const { return !hasUserDeclaredMoveAssignment() && hasMoveAssignment() && @@ -871,6 +879,15 @@ public: return data().UserDeclaredSpecialMembers & SMF_CopyAssignment; } + /// Set that we attempted to declare an implicit copy assignment + /// operator, but overload resolution failed so we deleted it. + void setImplicitCopyAssignmentIsDeleted() { + assert((data().DefaultedCopyAssignmentIsDeleted || + needsOverloadResolutionForCopyAssignment()) && + "copy assignment should not be deleted"); + data().DefaultedCopyAssignmentIsDeleted = true; + } + /// Determine whether this class needs an implicit copy /// assignment operator to be lazily declared. bool needsImplicitCopyAssignment() const { @@ -880,7 +897,16 @@ public: /// Determine whether we need to eagerly declare a defaulted copy /// assignment operator for this class. bool needsOverloadResolutionForCopyAssignment() const { - return data().HasMutableFields; + // C++20 [class.copy.assign]p2: + // If the class definition declares a move constructor or move assignment + // operator, the implicitly declared copy assignment operator is defined + // as deleted. + // In MSVC mode, sometimes a declared move constructor does not delete an + // implicit copy assignment, so defer this choice to Sema. + if (data().UserDeclaredSpecialMembers & + (SMF_MoveConstructor | SMF_MoveAssignment)) + return true; + return data().NeedOverloadResolutionForCopyAssignment; } /// Determine whether an implicit copy assignment operator for this @@ -998,6 +1024,9 @@ public: return static_cast<LambdaCaptureDefault>(getLambdaData().CaptureDefault); } + /// Set the captures for this lambda closure type. + void setCaptures(ArrayRef<LambdaCapture> Captures); + /// For a closure type, retrieve the mapping from captured /// variables and \c this to the non-static data members that store the /// values or references of the captures. @@ -1029,6 +1058,8 @@ public: : nullptr; } + unsigned capture_size() const { return getLambdaData().NumCaptures; } + using conversion_iterator = UnresolvedSetIterator; conversion_iterator conversion_begin() const { @@ -1166,7 +1197,7 @@ public: bool defaultedDefaultConstructorIsConstexpr() const { return data().DefaultedDefaultConstructorIsConstexpr && (!isUnion() || hasInClassInitializer() || !hasVariantMembers() || - getASTContext().getLangOpts().CPlusPlus2a); + getLangOpts().CPlusPlus20); } /// Determine whether this class has a constexpr default constructor. @@ -1258,7 +1289,7 @@ public: /// would be constexpr. bool defaultedDestructorIsConstexpr() const { return data().DefaultedDestructorIsConstexpr && - getASTContext().getLangOpts().CPlusPlus2a; + getLangOpts().CPlusPlus20; } /// Determine whether this class has a constexpr destructor. @@ -1355,10 +1386,10 @@ public: /// /// Only in C++17 and beyond, are lambdas literal types. bool isLiteral() const { - ASTContext &Ctx = getASTContext(); - return (Ctx.getLangOpts().CPlusPlus2a ? hasConstexprDestructor() + const LangOptions &LangOpts = getLangOpts(); + return (LangOpts.CPlusPlus20 ? hasConstexprDestructor() : hasTrivialDestructor()) && - (!isLambda() || Ctx.getLangOpts().CPlusPlus17) && + (!isLambda() || LangOpts.CPlusPlus17) && !hasNonLiteralTypeFieldsOrBases() && (isAggregate() || isLambda() || hasConstexprNonCopyMoveConstructor() || @@ -1517,14 +1548,8 @@ public: /// returns false if the class has non-computable base classes. /// /// \param BaseMatches Callback invoked for each (direct or indirect) base - /// class of this type, or if \p AllowShortCircuit is true then until a call - /// returns false. - /// - /// \param AllowShortCircuit if false, forces the callback to be called - /// for every base class, even if a dependent or non-matching base was - /// found. - bool forallBases(ForallBasesCallback BaseMatches, - bool AllowShortCircuit = true) const; + /// class of this type until a call returns false. + bool forallBases(ForallBasesCallback BaseMatches) const; /// Function type used by lookupInBases() to determine whether a /// specific base class subobject matches the lookup criteria. @@ -1696,6 +1721,10 @@ public: /// actually abstract. bool mayBeAbstract() const; + /// Determine whether it's impossible for a class to be derived from this + /// class. This is best-effort, and may conservatively return false. + bool isEffectivelyFinal() const; + /// If this is the closure type of a lambda expression, retrieve the /// number to be used for name mangling in the Itanium C++ ABI. /// @@ -1893,6 +1922,37 @@ public: static bool classofKind(Kind K) { return K == CXXDeductionGuide; } }; +/// \brief Represents the body of a requires-expression. +/// +/// This decl exists merely to serve as the DeclContext for the local +/// parameters of the requires expression as well as other declarations inside +/// it. +/// +/// \code +/// template<typename T> requires requires (T t) { {t++} -> regular; } +/// \endcode +/// +/// In this example, a RequiresExpr object will be generated for the expression, +/// and a RequiresExprBodyDecl will be created to hold the parameter t and the +/// template argument list imposed by the compound requirement. +class RequiresExprBodyDecl : public Decl, public DeclContext { + RequiresExprBodyDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc) + : Decl(RequiresExprBody, DC, StartLoc), DeclContext(RequiresExprBody) {} + +public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + + static RequiresExprBodyDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc); + + static RequiresExprBodyDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == RequiresExprBody; } +}; + /// Represents a static or instance method of a struct/union/class. /// /// In the terminology of the C++ Standard, these are the (static and @@ -2006,7 +2066,8 @@ public: method_iterator end_overridden_methods() const; unsigned size_overridden_methods() const; - using overridden_method_range= ASTContext::overridden_method_range; + using overridden_method_range = llvm::iterator_range< + llvm::TinyPtrVector<const CXXMethodDecl *>::const_iterator>; overridden_method_range overridden_methods() const; @@ -2386,17 +2447,6 @@ class CXXConstructorDecl final : ExplicitSpecKind::ResolvedFalse); } - void setExplicitSpecifier(ExplicitSpecifier ES) { - assert((!ES.getExpr() || - CXXConstructorDeclBits.HasTrailingExplicitSpecifier) && - "cannot set this explicit specifier. no trail-allocated space for " - "explicit"); - if (ES.getExpr()) - *getCanonicalDecl()->getTrailingObjects<ExplicitSpecifier>() = ES; - else - CXXConstructorDeclBits.IsSimpleExplicit = ES.isExplicit(); - } - enum TraillingAllocKind { TAKInheritsConstructor = 1, TAKHasTailExplicit = 1 << 1, @@ -2422,6 +2472,17 @@ public: InheritedConstructor Inherited = InheritedConstructor(), Expr *TrailingRequiresClause = nullptr); + void setExplicitSpecifier(ExplicitSpecifier ES) { + assert((!ES.getExpr() || + CXXConstructorDeclBits.HasTrailingExplicitSpecifier) && + "cannot set this explicit specifier. no trail-allocated space for " + "explicit"); + if (ES.getExpr()) + *getCanonicalDecl()->getTrailingObjects<ExplicitSpecifier>() = ES; + else + CXXConstructorDeclBits.IsSimpleExplicit = ES.isExplicit(); + } + ExplicitSpecifier getExplicitSpecifier() { return getCanonicalDecl()->getExplicitSpecifierInternal(); } @@ -2693,8 +2754,6 @@ class CXXConversionDecl : public CXXMethodDecl { ExplicitSpecifier ExplicitSpec; - void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; } - public: friend class ASTDeclReader; friend class ASTDeclWriter; @@ -2716,6 +2775,7 @@ public: /// Return true if the declartion is already resolved to be explicit. bool isExplicit() const { return getExplicitSpecifier().isExplicit(); } + void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; } /// Returns the type that this conversion function is converting to. QualType getConversionType() const { @@ -3933,6 +3993,81 @@ public: IdentifierInfo* getSetterId() const { return SetterId; } }; +/// Parts of a decomposed MSGuidDecl. Factored out to avoid unnecessary +/// dependencies on DeclCXX.h. +struct MSGuidDeclParts { + /// {01234567-... + uint32_t Part1; + /// ...-89ab-... + uint16_t Part2; + /// ...-cdef-... + uint16_t Part3; + /// ...-0123-456789abcdef} + uint8_t Part4And5[8]; + + uint64_t getPart4And5AsUint64() const { + uint64_t Val; + memcpy(&Val, &Part4And5, sizeof(Part4And5)); + return Val; + } +}; + +/// A global _GUID constant. These are implicitly created by UuidAttrs. +/// +/// struct _declspec(uuid("01234567-89ab-cdef-0123-456789abcdef")) X{}; +/// +/// X is a CXXRecordDecl that contains a UuidAttr that references the (unique) +/// MSGuidDecl for the specified UUID. +class MSGuidDecl : public ValueDecl, + public Mergeable<MSGuidDecl>, + public llvm::FoldingSetNode { +public: + using Parts = MSGuidDeclParts; + +private: + /// The decomposed form of the UUID. + Parts PartVal; + + /// The resolved value of the UUID as an APValue. Computed on demand and + /// cached. + mutable APValue APVal; + + void anchor() override; + + MSGuidDecl(DeclContext *DC, QualType T, Parts P); + + static MSGuidDecl *Create(const ASTContext &C, QualType T, Parts P); + static MSGuidDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + // Only ASTContext::getMSGuidDecl and deserialization create these. + friend class ASTContext; + friend class ASTReader; + friend class ASTDeclReader; + +public: + /// Print this UUID in a human-readable format. + void printName(llvm::raw_ostream &OS) const override; + + /// Get the decomposed parts of this declaration. + Parts getParts() const { return PartVal; } + + /// Get the value of this MSGuidDecl as an APValue. This may fail and return + /// an absent APValue if the type of the declaration is not of the expected + /// shape. + APValue &getAsAPValue() const; + + static void Profile(llvm::FoldingSetNodeID &ID, Parts P) { + ID.AddInteger(P.Part1); + ID.AddInteger(P.Part2); + ID.AddInteger(P.Part3); + ID.AddInteger(P.getPart4And5AsUint64()); + } + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, PartVal); } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Decl::MSGuid; } +}; + /// Insertion operator for diagnostics. This allows sending an AccessSpecifier /// into a diagnostic with <<. const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
