From: Abramo Bagnara Date: Fri, 3 Dec 2010 18:54:17 +0000 (+0000) Subject: Added struct/class syntactic info for c++0x scoped enum. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a88cefd266c428be33cc06f7e8b00ff8fc97c1ff;p=clang Added struct/class syntactic info for c++0x scoped enum. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120828 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index fca141a6b8..f2cb672bb8 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -1964,9 +1964,14 @@ protected: unsigned NumPositiveBits : 8; unsigned NumNegativeBits : 8; - /// IsScoped - True if this is tag declaration is a scoped enumeration. Only + /// IsScoped - True if this tag declaration is a scoped enumeration. Only /// possible in C++0x mode. bool IsScoped : 1; + /// IsScopedUsingClassTag - 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. + bool IsScopedUsingClassTag : 1; /// IsFixed - True if this is an enumeration with fixed underlying type. Only /// possible in C++0x mode. @@ -2189,12 +2194,14 @@ class EnumDecl : public TagDecl { EnumDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL, - bool Scoped, bool Fixed) + bool Scoped, bool ScopedUsingClassTag, bool Fixed) : TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { + assert(Scoped || !ScopedUsingClassTag); IntegerType = (const Type*)0; NumNegativeBits = 0; NumPositiveBits = 0; IsScoped = Scoped; + IsScopedUsingClassTag = ScopedUsingClassTag; IsFixed = Fixed; } public: @@ -2215,7 +2222,8 @@ public: static EnumDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation TKL, EnumDecl *PrevDecl, - bool IsScoped, bool IsFixed); + bool IsScoped, bool IsScopedUsingClassTag, + bool IsFixed); static EnumDecl *Create(ASTContext &C, EmptyShell Empty); /// completeDefinition - When created, the EnumDecl corresponds to a @@ -2306,6 +2314,11 @@ public: return IsScoped; } + /// \brief Returns true if this is a C++0x scoped enumeration. + bool isScopedUsingClassTag() const { + return IsScopedUsingClassTag; + } + /// \brief Returns true if this is a C++0x enumeration with fixed underlying /// type. bool isFixed() const { diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index b8b30eab7b..93b5884d91 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -808,7 +808,7 @@ public: AttributeList *Attr, AccessSpecifier AS, MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, bool &IsDependent, bool ScopedEnum, - TypeResult UnderlyingType); + bool ScopedEnumUsesClassTag, TypeResult UnderlyingType); Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index e9bb3ad960..c4d1181528 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -2001,9 +2001,10 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Create the enum declaration. EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo(), - Importer.Import(D->getTagKeywordLoc()), - 0, D->isScoped(), D->isFixed()); + Name.getAsIdentifierInfo(), + Importer.Import(D->getTagKeywordLoc()), 0, + D->isScoped(), D->isScopedUsingClassTag(), + D->isFixed()); // Import the qualifier, if any. if (D->getQualifier()) { NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 19fbf69d37..76d67bca1a 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1925,16 +1925,17 @@ void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier, EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation TKL, - EnumDecl *PrevDecl, bool IsScoped, bool IsFixed) { + EnumDecl *PrevDecl, bool IsScoped, + bool IsScopedUsingClassTag, bool IsFixed) { EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, PrevDecl, TKL, - IsScoped, IsFixed); + IsScoped, IsScopedUsingClassTag, IsFixed); C.getTypeDeclType(Enum, PrevDecl); return Enum; } EnumDecl *EnumDecl::Create(ASTContext &C, EmptyShell Empty) { return new (C) EnumDecl(0, SourceLocation(), 0, 0, SourceLocation(), - false, false); + false, false, false); } void EnumDecl::completeDefinition(QualType NewType, diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 5a31440494..143238b4ae 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -308,8 +308,12 @@ void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { void DeclPrinter::VisitEnumDecl(EnumDecl *D) { Out << "enum "; - if (D->isScoped()) - Out << "class "; + if (D->isScoped()) { + if (D->isScopedUsingClassTag()) + Out << "class "; + else + Out << "struct "; + } Out << D; if (D->isFixed()) { diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index f1fb7b29a1..9a682b064d 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1980,11 +1980,13 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, } bool IsScopedEnum = false; + bool IsScopedUsingClassTag = false; - if (getLang().CPlusPlus0x && (Tok.is(tok::kw_class) - || Tok.is(tok::kw_struct))) { - ConsumeToken(); + if (getLang().CPlusPlus0x && + (Tok.is(tok::kw_class) || Tok.is(tok::kw_struct))) { IsScopedEnum = true; + IsScopedUsingClassTag = Tok.is(tok::kw_class); + ConsumeToken(); } // Must have either 'enum name' or 'enum {...}'. @@ -2009,6 +2011,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // declaration of a scoped enumeration. Diag(Tok, diag::err_scoped_enum_missing_identifier); IsScopedEnum = false; + IsScopedUsingClassTag = false; } TypeResult BaseType; @@ -2103,7 +2106,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, AS, MultiTemplateParamsArg(Actions), Owned, IsDependent, IsScopedEnum, - BaseType); + IsScopedUsingClassTag, BaseType); if (IsDependent) { // This enum has a dependent nested-name-specifier. Handle it as a diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 1bc5815f21..68797a7542 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1002,7 +1002,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, AttrList, AS, TParams, Owned, IsDependent, false, - clang::TypeResult()); + false, clang::TypeResult()); // If ActOnTag said the type was dependent, try again with the // less common call. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7b0afe1963..ff90670b7c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5643,7 +5643,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, AccessSpecifier AS, MultiTemplateParamsArg TemplateParameterLists, - bool &OwnedDecl, bool &IsDependent, bool ScopedEnum, + bool &OwnedDecl, bool &IsDependent, + bool ScopedEnum, bool ScopedEnumUsesClassTag, TypeResult UnderlyingType) { // If this is not a definition, it must have a name. assert((Name != 0 || TUK == TUK_Definition) && @@ -6139,7 +6140,7 @@ CreateNewDecl: // enum X { A, B, C } D; D should chain to X. New = EnumDecl::Create(Context, SearchDC, Loc, Name, KWLoc, cast_or_null(PrevDecl), ScopedEnum, - !EnumUnderlying.isNull()); + ScopedEnumUsesClassTag, !EnumUnderlying.isNull()); // If this is an undefined enum, warn. if (TUK != TUK_Definition && !Invalid) { TagDecl *Def; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 53d7c10ede..1a8c44a0e6 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5172,7 +5172,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference, KWLoc, SS, Name, NameLoc, Attr, AS_none, MultiTemplateParamsArg(*this, 0, 0), - Owned, IsDependent, false, + Owned, IsDependent, false, false, TypeResult()); assert(!IsDependent && "explicit instantiation of dependent name not yet handled"); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index b45fb821d9..e299be9879 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -540,8 +540,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getIdentifier(), D->getTagKeywordLoc(), - /*PrevDecl=*/0, - D->isScoped(), D->isFixed()); + /*PrevDecl=*/0, D->isScoped(), + D->isScopedUsingClassTag(), D->isFixed()); if (D->isFixed()) { if (TypeSourceInfo* TI = D->getIntegerTypeSourceInfo()) { // If we have type source information for the underlying type, it means it diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index c21dfc2b1f..7053f404e4 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -242,6 +242,7 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { ED->setNumPositiveBits(Record[Idx++]); ED->setNumNegativeBits(Record[Idx++]); ED->IsScoped = Record[Idx++]; + ED->IsScopedUsingClassTag = Record[Idx++]; ED->IsFixed = Record[Idx++]; ED->setInstantiationOfMemberEnum( cast_or_null(Reader.GetDecl(Record[Idx++]))); diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 27adb26d71..ef8914b7a2 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -190,6 +190,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { Record.push_back(D->getNumPositiveBits()); Record.push_back(D->getNumNegativeBits()); Record.push_back(D->isScoped()); + Record.push_back(D->isScopedUsingClassTag()); Record.push_back(D->isFixed()); Writer.AddDeclRef(D->getInstantiatedFromMemberEnum(), Record); Code = serialization::DECL_ENUM;