diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index cc59acbca99d..51f72736e9dd 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1608,6 +1608,7 @@ private: unsigned SClass : 2; unsigned IsInline : 1; unsigned IsInlineSpecified : 1; + unsigned IsExplicitSpecified : 1; unsigned IsVirtualAsWritten : 1; unsigned IsPure : 1; unsigned HasInheritedPrototype : 1; @@ -1708,8 +1709,9 @@ protected: StartLoc), DeclContext(DK), redeclarable_base(C), ParamInfo(nullptr), Body(), SClass(S), IsInline(isInlineSpecified), - IsInlineSpecified(isInlineSpecified), IsVirtualAsWritten(false), - IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), + IsInlineSpecified(isInlineSpecified), IsExplicitSpecified(false), + IsVirtualAsWritten(false), IsPure(false), + HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), IsDefaulted(false), IsExplicitlyDefaulted(false), HasImplicitReturnZero(false), IsLateTemplateParsed(false), IsConstexpr(isConstexprSpecified), @@ -1853,6 +1855,19 @@ public: bool isVirtualAsWritten() const { return IsVirtualAsWritten; } void setVirtualAsWritten(bool V) { IsVirtualAsWritten = V; } + /// Whether this function is marked as explicit explicitly. + bool isExplicitSpecified() const { return IsExplicitSpecified; } + void setExplicitSpecified() { + assert((getKind() == CXXConstructor || getKind() == CXXConversion || + isDeductionGuide()) && "cannot be explicit"); + IsExplicitSpecified = true; + } + + /// Whether this function is explicit. + bool isExplicit() const { + return getFirstDecl()->isExplicitSpecified(); + } + /// Whether this virtual function is pure, i.e. makes the containing class /// abstract. bool isPure() const { return IsPure; } diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 0ca08db16299..020ebfb4af9b 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2161,13 +2161,9 @@ class CXXConstructorDecl final /// \{ /// \brief The arguments used to initialize the base or member. LazyCXXCtorInitializersPtr CtorInitializers; - unsigned NumCtorInitializers : 30; + unsigned NumCtorInitializers : 31; /// \} - /// \brief Whether this constructor declaration has the \c explicit keyword - /// specified. - unsigned IsExplicitSpecified : 1; - /// \brief Whether this constructor declaration is an implicitly-declared /// inheriting constructor. unsigned IsInheritingConstructor : 1; @@ -2181,11 +2177,12 @@ class CXXConstructorDecl final : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, isConstexpr, SourceLocation()), CtorInitializers(nullptr), NumCtorInitializers(0), - IsExplicitSpecified(isExplicitSpecified), IsInheritingConstructor((bool)Inherited) { setImplicit(isImplicitlyDeclared); if (Inherited) *getTrailingObjects() = Inherited; + if (isExplicitSpecified) + setExplicitSpecified(); } public: @@ -2198,15 +2195,6 @@ public: bool isConstexpr, InheritedConstructor Inherited = InheritedConstructor()); - /// \brief Determine whether this constructor declaration has the - /// \c explicit keyword specified. - bool isExplicitSpecified() const { return IsExplicitSpecified; } - - /// \brief Determine whether this constructor was marked "explicit" or not. - bool isExplicit() const { - return cast(getFirstDecl())->isExplicitSpecified(); - } - /// \brief Iterates through the member/base initializer list. typedef CXXCtorInitializer **init_iterator; @@ -2428,19 +2416,17 @@ public: /// \endcode class CXXConversionDecl : public CXXMethodDecl { void anchor() override; - /// Whether this conversion function declaration is marked - /// "explicit", meaning that it can only be applied when the user - /// explicitly wrote a cast. This is a C++11 feature. - bool IsExplicitSpecified : 1; CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isExplicitSpecified, - bool isConstexpr, SourceLocation EndLocation) - : CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, isConstexpr, EndLocation), - IsExplicitSpecified(isExplicitSpecified) { } + const DeclarationNameInfo &NameInfo, QualType T, + TypeSourceInfo *TInfo, bool isInline, + bool isExplicitSpecified, bool isConstexpr, + SourceLocation EndLocation) + : CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo, + SC_None, isInline, isConstexpr, EndLocation) { + if (isExplicitSpecified) + setExplicitSpecified(); + } public: static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, @@ -2452,19 +2438,6 @@ public: SourceLocation EndLocation); static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID); - /// Whether this conversion function declaration is marked - /// "explicit", meaning that it can only be used for direct initialization - /// (including explitly written casts). This is a C++11 feature. - bool isExplicitSpecified() const { return IsExplicitSpecified; } - - /// \brief Whether this is an explicit conversion operator (C++11 and later). - /// - /// Explicit conversion operators are only considered for direct - /// initialization, e.g., when the user has explicitly written a cast. - bool isExplicit() const { - return cast(getFirstDecl())->isExplicitSpecified(); - } - /// \brief Returns the type that this conversion function is converting to. QualType getConversionType() const { return getType()->getAs()->getReturnType(); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index afda1a83c2aa..5638cdfde5d2 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -743,6 +743,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->SClass = (StorageClass)Record.readInt(); FD->IsInline = Record.readInt(); FD->IsInlineSpecified = Record.readInt(); + FD->IsExplicitSpecified = Record.readInt(); FD->IsVirtualAsWritten = Record.readInt(); FD->IsPure = Record.readInt(); FD->HasInheritedPrototype = Record.readInt(); @@ -1809,8 +1810,6 @@ void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { } VisitCXXMethodDecl(D); - - D->IsExplicitSpecified = Record.readInt(); } void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { @@ -1826,7 +1825,6 @@ void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { VisitCXXMethodDecl(D); - D->IsExplicitSpecified = Record.readInt(); } void ASTDeclReader::VisitImportDecl(ImportDecl *D) { diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 6629036809f6..3144b87cd459 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -520,6 +520,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.push_back((int)D->SClass); // FIXME: stable encoding Record.push_back(D->IsInline); Record.push_back(D->IsInlineSpecified); + Record.push_back(D->IsExplicitSpecified); Record.push_back(D->IsVirtualAsWritten); Record.push_back(D->IsPure); Record.push_back(D->HasInheritedPrototype); @@ -1269,8 +1270,6 @@ void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { VisitCXXMethodDecl(D); - Record.push_back(D->IsExplicitSpecified); - Code = D->isInheritingConstructor() ? serialization::DECL_CXX_INHERITED_CONSTRUCTOR : serialization::DECL_CXX_CONSTRUCTOR; @@ -1286,7 +1285,6 @@ void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { void ASTDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) { VisitCXXMethodDecl(D); - Record.push_back(D->IsExplicitSpecified); Code = serialization::DECL_CXX_CONVERSION; } @@ -2024,6 +2022,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // StorageClass Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Inline Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InlineSpecified + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitSpecified Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // VirtualAsWritten Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Pure Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedProto