diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 29 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 6 |
4 files changed, 31 insertions, 12 deletions
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 5d4fce787ee..46914f68040 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -1118,6 +1118,7 @@ bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc, switch (VS) { default: llvm_unreachable("Unknown specifier!"); case VS_Override: VS_overrideLoc = Loc; break; + case VS_Sealed: case VS_Final: VS_finalLoc = Loc; break; } @@ -1129,5 +1130,6 @@ const char *VirtSpecifiers::getSpecifierName(Specifier VS) { default: llvm_unreachable("Unknown specifier"); case VS_Override: return "override"; case VS_Final: return "final"; + case VS_Sealed: return "sealed"; } } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f56ef429329..632cc19c485 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10957,6 +10957,7 @@ Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) { void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, SourceLocation FinalLoc, + bool IsFinalSpelledSealed, SourceLocation LBraceLoc) { AdjustDeclIfTemplate(TagD); CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD); @@ -10967,8 +10968,9 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, return; if (FinalLoc.isValid()) - Record->addAttr(new (Context) FinalAttr(FinalLoc, Context)); - + Record->addAttr(new (Context) + FinalAttr(FinalLoc, Context, IsFinalSpelledSealed)); + // C++ [class]p2: // [...] The class-name is also inserted into the scope of the // class itself; this is known as the injected-class-name. For diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index bd864b3adbc..81283e1f782 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1373,9 +1373,10 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // C++ [class]p3: // If a class is marked final and it appears as a base-type-specifier in // base-clause, the program is ill-formed. - if (CXXBaseDecl->hasAttr<FinalAttr>()) { + if (FinalAttr *FA = CXXBaseDecl->getAttr<FinalAttr>()) { Diag(BaseLoc, diag::err_class_marked_final_used_as_base) - << CXXBaseDecl->getDeclName(); + << CXXBaseDecl->getDeclName() + << FA->isSpelledAsSealed(); Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl) << CXXBaseDecl->getDeclName(); return 0; @@ -1762,7 +1763,8 @@ void Sema::CheckOverrideControl(NamedDecl *D) { } else if (FinalAttr *FA = D->getAttr<FinalAttr>()) { Diag(FA->getLocation(), diag::override_keyword_hides_virtual_member_function) - << "final" << (OverloadedMethods.size() > 1); + << (FA->isSpelledAsSealed() ? "sealed" : "final") + << (OverloadedMethods.size() > 1); } NoteHiddenVirtualMethods(MD, OverloadedMethods); MD->setInvalidDecl(); @@ -1782,7 +1784,8 @@ void Sema::CheckOverrideControl(NamedDecl *D) { if (FinalAttr *FA = D->getAttr<FinalAttr>()) { Diag(FA->getLocation(), diag::override_keyword_only_allowed_on_virtual_member_functions) - << "final" << FixItHint::CreateRemoval(FA->getLocation()); + << (FA->isSpelledAsSealed() ? "sealed" : "final") + << FixItHint::CreateRemoval(FA->getLocation()); D->dropAttr<FinalAttr>(); } return; @@ -1804,11 +1807,13 @@ void Sema::CheckOverrideControl(NamedDecl *D) { /// C++11 [class.virtual]p4. bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, const CXXMethodDecl *Old) { - if (!Old->hasAttr<FinalAttr>()) + FinalAttr *FA = Old->getAttr<FinalAttr>(); + if (!FA) return false; Diag(New->getLocation(), diag::err_final_function_overridden) - << New->getDeclName(); + << New->getDeclName() + << FA->isSpelledAsSealed(); Diag(Old->getLocation(), diag::note_overridden_virtual_function); return true; } @@ -2067,7 +2072,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (VS.isOverrideSpecified()) Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context)); if (VS.isFinalSpecified()) - Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context)); + Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context, + VS.isFinalSpelledSealed())); if (VS.getLastLocation().isValid()) { // Update the end location of a method that has a virt-specifiers. @@ -4406,9 +4412,12 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { diag::warn_non_virtual_dtor) << Context.getRecordType(Record); } - if (Record->isAbstract() && Record->hasAttr<FinalAttr>()) { - Diag(Record->getLocation(), diag::warn_abstract_final_class); - DiagnoseAbstractType(Record); + if (Record->isAbstract()) { + if (FinalAttr *FA = Record->getAttr<FinalAttr>()) { + Diag(Record->getLocation(), diag::warn_abstract_final_class) + << FA->isSpelledAsSealed(); + DiagnoseAbstractType(Record); + } } if (!Record->isDependentType()) { diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 837d383a1bb..323cd265e6c 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3131,6 +3131,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, // These traits require a complete type. case UTT_IsFinal: + case UTT_IsSealed: // These trait expressions are designed to help implement predicates in // [meta.unary.prop] despite not being named the same. They are specified @@ -3304,6 +3305,11 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) return RD->hasAttr<FinalAttr>(); return false; + case UTT_IsSealed: + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + if (FinalAttr *FA = RD->getAttr<FinalAttr>()) + return FA->isSpelledAsSealed(); + return false; case UTT_IsSigned: return T->isSignedIntegerType(); case UTT_IsUnsigned: |