From: Anders Carlsson Date: Mon, 24 Jan 2011 16:26:15 +0000 (+0000) Subject: Use attributes for all the override control specifiers. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cb88a1f968c3d4eb451dafb421a8d9578edcbf1a;p=clang Use attributes for all the override control specifiers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124122 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 25424ce853..a34a2ef535 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -1195,8 +1195,6 @@ private: bool IsDeleted : 1; bool IsTrivial : 1; // sunk from CXXMethodDecl bool HasImplicitReturnZero : 1; - bool IsMarkedOverride : 1; // sunk from CXXMethodDecl - bool IsMarkedFinal : 1; // sunk from CXXMethodDecl /// \brief End part of this FunctionDecl's source range. /// @@ -1276,8 +1274,7 @@ protected: IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), - HasImplicitReturnZero(false), IsMarkedOverride(false), - IsMarkedFinal(false), EndRangeLoc(NameInfo.getEndLoc()), + HasImplicitReturnZero(false), EndRangeLoc(NameInfo.getEndLoc()), TemplateOrSpecialization(), DNLoc(NameInfo.getInfo()) {} @@ -1390,16 +1387,6 @@ public: bool hasImplicitReturnZero() const { return HasImplicitReturnZero; } void setHasImplicitReturnZero(bool IRZ) { HasImplicitReturnZero = IRZ; } - /// \brief Whether this member function is marked with the 'override' keyword, - /// C++0x [class.mem]p8. - bool isMarkedOverride() const { return IsMarkedOverride; } - void setIsMarkedOverride(bool IMO) { IsMarkedOverride = IMO; } - - /// \brief Whether this member function is marked with the 'final' keyword, - /// C++0x [class.mem]p8. - bool isMarkedFinal() const { return IsMarkedFinal; } - void setIsMarkedFinal(bool IMF) { IsMarkedFinal = IMF; } - /// \brief Whether this function has a prototype, either because one /// was explicitly written or because it was "inherited" by merging /// a declaration without a prototype with a declaration that has a diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index cc3e4a52aa..a09fd6741b 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -356,12 +356,6 @@ class CXXRecordDecl : public RecordDecl { /// \brief Whether we have already declared a destructor within the class. bool DeclaredDestructor : 1; - /// \brief Whether this class is marked 'final'. - bool IsMarkedFinal : 1; - - /// \brief Whether this class is marked 'explicit'. - bool IsMarkedExplicit : 1; - /// NumBases - The number of base class specifiers in Bases. unsigned NumBases; @@ -665,18 +659,6 @@ public: /// This value is used for lazy creation of destructors. bool hasDeclaredDestructor() const { return data().DeclaredDestructor; } - /// \brief Whether this class is marked 'final'. - bool isMarkedFinal() const { return data().IsMarkedFinal; } - - /// \brief Mark this class as 'final'. - void setIsMarkedFinal(bool IMF) { data().IsMarkedFinal = IMF; } - - /// \brief Whether this class is marked 'explicit'. - bool isMarkedExplicit() const { return data().IsMarkedExplicit; } - - /// \brief Mark this class as 'explicit'. - void setIsMarkedExplicit(bool IME) { data().IsMarkedExplicit = IME; } - /// getConversions - Retrieve the overload set containing all of the /// conversion functions in this class. UnresolvedSetImpl *getConversionFunctions() { diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 9a13ce6391..49d3ab6239 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -213,10 +213,18 @@ def DLLImport : InheritableAttr { let Spellings = ["dllimport"]; } +def Explicit : InheritableAttr { + let Spellings = []; +} + def FastCall : InheritableAttr { let Spellings = ["fastcall", "__fastcall"]; } +def Final : InheritableAttr { + let Spellings = []; +} + def Format : InheritableAttr { let Spellings = ["format"]; let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">, @@ -336,6 +344,10 @@ def Overloadable : Attr { let Spellings = ["overloadable"]; } +def Override : InheritableAttr { + let Spellings = []; +} + def Ownership : InheritableAttr { let Spellings = ["ownership_holds", "ownership_returns", "ownership_takes"]; let Args = [EnumArgument<"OwnKind", "OwnershipKind", diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 370cbfc0f1..bce8b92c48 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -36,9 +36,8 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) HasTrivialDestructor(true), ComputedVisibleConversions(false), DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), DeclaredCopyAssignment(false), DeclaredDestructor(false), - IsMarkedFinal(false), IsMarkedExplicit(false), - NumBases(0), NumVBases(0), Bases(), VBases(), - Definition(D), FirstFriend(0) { + NumBases(0), NumVBases(0), Bases(), VBases(), + Definition(D), FirstFriend(0) { } CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 9ce90c0ce8..7177a64e74 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -65,12 +65,12 @@ static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context, // If the member function is marked 'final', we know that it can't be // overridden and can therefore devirtualize it. - if (MD->isMarkedFinal()) + if (MD->hasAttr()) return true; // Similarly, if the class itself is marked 'final' it can't be overridden // and we can therefore devirtualize the member function call. - if (MD->getParent()->isMarkedFinal()) + if (MD->getParent()->hasAttr()) return true; if (const DeclRefExpr *DRE = dyn_cast(Base)) { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 85df57a76c..4d8179738a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -6386,8 +6386,10 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, if (!Record->getIdentifier()) return; - Record->setIsMarkedFinal(CVS.isFinalSpecified()); - Record->setIsMarkedExplicit(CVS.isExplicitSpecified()); + if (CVS.isFinalSpecified()) + Record->addAttr(new (Context) FinalAttr(CVS.getFinalLoc(), Context)); + if (CVS.isExplicitSpecified()) + Record->addAttr(new (Context) ExplicitAttr(CVS.getExplicitLoc(), Context)); // C++ [class]p2: // [...] The class-name is also inserted into the scope of the diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index eeb665b61d..25d0a5effe 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -525,7 +525,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // If a class is marked with the class-virt-specifier final and it appears // as a base-type-specifier in a base-clause (10 class.derived), the program // is ill-formed. - if (CXXBaseDecl->isMarkedFinal()) { + if (CXXBaseDecl->hasAttr()) { Diag(BaseLoc, diag::err_class_marked_final_used_as_base) << CXXBaseDecl->getDeclName(); Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl) @@ -871,7 +871,7 @@ void Sema::CheckOverrideControl(const Decl *D) { // the program is ill-formed. bool HasOverriddenMethods = MD->begin_overridden_methods() != MD->end_overridden_methods(); - if (MD->isMarkedOverride() && !HasOverriddenMethods) { + if (MD->hasAttr() && !HasOverriddenMethods) { Diag(MD->getLocation(), diag::err_function_marked_override_not_overriding) << MD->getDeclName(); @@ -883,8 +883,8 @@ void Sema::CheckOverrideControl(const Decl *D) { // if a virtual member function that is neither implicitly-declared nor a // destructor overrides a member function of a base class and it is not // marked with the virt-specifier override, the program is ill-formed. - if (MD->getParent()->isMarkedExplicit() && !isa(MD) && - HasOverriddenMethods && !MD->isMarkedOverride()) { + if (MD->getParent()->hasAttr() && !isa(MD) && + HasOverriddenMethods && !MD->hasAttr()) { llvm::SmallVector OverriddenMethods(MD->begin_overridden_methods(), MD->end_overridden_methods()); @@ -904,7 +904,7 @@ void Sema::CheckOverrideControl(const Decl *D) { /// C++0x [class.virtual]p3. bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, const CXXMethodDecl *Old) { - if (!Old->isMarkedFinal()) + if (!Old->hasAttr()) return false; Diag(New->getLocation(), diag::err_final_function_overridden) @@ -1057,7 +1057,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, diag::override_keyword_only_allowed_on_virtual_member_functions) << "override" << FixItHint::CreateRemoval(VS.getOverrideLoc()); } else - MD->setIsMarkedOverride(true); + MD->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context)); } if (VS.isFinalSpecified()) { CXXMethodDecl *MD = dyn_cast(Member); @@ -1066,7 +1066,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, diag::override_keyword_only_allowed_on_virtual_member_functions) << "final" << FixItHint::CreateRemoval(VS.getFinalLoc()); } else - MD->setIsMarkedFinal(true); + MD->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context)); } CheckOverrideControl(Member); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 2102073682..45fde296e3 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1640,9 +1640,6 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, Instantiation->setTagKind(Pattern->getTagKind()); - Instantiation->setIsMarkedFinal(Pattern->isMarkedFinal()); - Instantiation->setIsMarkedExplicit(Pattern->isMarkedExplicit()); - // Do substitution on the base class specifiers. if (SubstBaseSpecifiers(Instantiation, Pattern, TemplateArgs)) Invalid = true; diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 5238ad6dfc..759e2c16f1 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1389,8 +1389,6 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, if (D->isPure()) SemaRef.CheckPureMethod(Method, SourceRange()); - Method->setIsMarkedOverride(D->isMarkedOverride()); - Method->setIsMarkedFinal(D->isMarkedFinal()); Method->setAccess(D->getAccess()); SemaRef.CheckOverrideControl(Method); diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 453820cc4a..26baee47c2 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -395,9 +395,6 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->IsDeleted = Record[Idx++]; FD->IsTrivial = Record[Idx++]; FD->HasImplicitReturnZero = Record[Idx++]; - FD->IsMarkedOverride = Record[Idx++]; - FD->IsMarkedFinal = Record[Idx++]; - FD->EndRangeLoc = ReadSourceLocation(Record, Idx); // Read in the parameters. @@ -800,8 +797,6 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.DeclaredCopyConstructor = Record[Idx++]; Data.DeclaredCopyAssignment = Record[Idx++]; Data.DeclaredDestructor = Record[Idx++]; - Data.IsMarkedFinal = Record[Idx++]; - Data.IsMarkedExplicit = Record[Idx++]; Data.NumBases = Record[Idx++]; if (Data.NumBases) diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index ea6b80762a..1e296e8514 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -3394,8 +3394,6 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Data.DeclaredCopyConstructor); Record.push_back(Data.DeclaredCopyAssignment); Record.push_back(Data.DeclaredDestructor); - Record.push_back(Data.IsMarkedFinal); - Record.push_back(Data.IsMarkedExplicit); Record.push_back(Data.NumBases); if (Data.NumBases > 0) diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 88ff1a7c9b..507c66931c 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -312,8 +312,6 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.push_back(D->isDeleted()); Record.push_back(D->isTrivial()); Record.push_back(D->hasImplicitReturnZero()); - Record.push_back(D->isMarkedOverride()); - Record.push_back(D->isMarkedFinal()); Writer.AddSourceLocation(D->getLocEnd(), Record); Record.push_back(D->param_size());