Author: majnemer Date: Thu Oct 17 19:33:31 2013 New Revision: 192936 URL: http://llvm.org/viewvc/llvm-project?rev=192936&view=rev Log: [-fms-extensions] Permit 'override' in C++98 and 'sealed' as a synonym for 'final'
Summary: Some MS headers use these features. Reviewers: rnk, rsmith CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1948 Modified: cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Basic/TokenKinds.def cfe/trunk/include/clang/Basic/TypeTraits.h cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/include/clang/Sema/DeclSpec.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/StmtPrinter.cpp cfe/trunk/lib/Lex/PPMacroExpansion.cpp cfe/trunk/lib/Parse/ParseDeclCXX.cpp cfe/trunk/lib/Parse/ParseExpr.cpp cfe/trunk/lib/Parse/ParseExprCXX.cpp cfe/trunk/lib/Parse/ParseTentative.cpp cfe/trunk/lib/Parse/Parser.cpp cfe/trunk/lib/Sema/DeclSpec.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaExprCXX.cpp cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp cfe/trunk/test/SemaCXX/type-traits.cpp Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Thu Oct 17 19:33:31 2013 @@ -395,7 +395,8 @@ def FastCall : InheritableAttr { } def Final : InheritableAttr { - let Spellings = []; + let Spellings = [Keyword<"final">, Keyword<"sealed">]; + let Accessors = [Accessor<"isSpelledAsSealed", [Keyword<"sealed">]>]; let SemaHandler = 0; } Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Oct 17 19:33:31 2013 @@ -704,6 +704,9 @@ def warn_cxx98_compat_override_control_k InGroup<CXX98Compat>, DefaultIgnore; def err_override_control_interface : Error< "'%0' keyword not permitted with interface types">; +def ext_ms_sealed_keyword : ExtWarn< + "'sealed' keyword is a Microsoft extension">, + InGroup<Microsoft>; def err_access_specifier_interface : Error< "interface types cannot specify '%select{private|protected}0' access">; Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Oct 17 19:33:31 2013 @@ -1552,16 +1552,16 @@ def override_keyword_hides_virtual_membe def err_function_marked_override_not_overriding : Error< "%0 marked 'override' but does not override any member functions">; def err_class_marked_final_used_as_base : Error< - "base %0 is marked 'final'">; + "base %0 is marked '%select{final|sealed}1'">; def warn_abstract_final_class : Warning< - "abstract class is marked 'final'">, InGroup<AbstractFinalClass>; + "abstract class is marked '%select{final|sealed}0'">, InGroup<AbstractFinalClass>; // C++11 attributes def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">; // C++11 final def err_final_function_overridden : Error< - "declaration of %0 overrides a 'final' function">; + "declaration of %0 overrides a '%select{final|sealed}1' function">; // C++11 scoped enumerations def err_enum_invalid_underlying : Error< Modified: cfe/trunk/include/clang/Basic/TokenKinds.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TokenKinds.def (original) +++ cfe/trunk/include/clang/Basic/TokenKinds.def Thu Oct 17 19:33:31 2013 @@ -350,6 +350,7 @@ KEYWORD(typeof , KE // MS Extensions KEYWORD(L__FUNCTION__ , KEYMS) +KEYWORD(__is_sealed , KEYMS) // GNU and MS Type Traits KEYWORD(__has_nothrow_assign , KEYCXX) Modified: cfe/trunk/include/clang/Basic/TypeTraits.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TypeTraits.h?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TypeTraits.h (original) +++ cfe/trunk/include/clang/Basic/TypeTraits.h Thu Oct 17 19:33:31 2013 @@ -57,6 +57,7 @@ namespace clang { UTT_IsReference, UTT_IsRvalueReference, UTT_IsScalar, + UTT_IsSealed, UTT_IsSigned, UTT_IsStandardLayout, UTT_IsTrivial, Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Thu Oct 17 19:33:31 2013 @@ -102,6 +102,7 @@ class Parser : public CodeCompletionHand /// Contextual keywords for Microsoft extensions. IdentifierInfo *Ident__except; + mutable IdentifierInfo *Ident_sealed; /// Ident_super - IdentifierInfo for "super", to support fast /// comparison. Modified: cfe/trunk/include/clang/Sema/DeclSpec.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/DeclSpec.h (original) +++ cfe/trunk/include/clang/Sema/DeclSpec.h Thu Oct 17 19:33:31 2013 @@ -2107,7 +2107,8 @@ public: enum Specifier { VS_None = 0, VS_Override = 1, - VS_Final = 2 + VS_Final = 2, + VS_Sealed = 4 }; VirtSpecifiers() : Specifiers(0) { } @@ -2118,7 +2119,8 @@ public: bool isOverrideSpecified() const { return Specifiers & VS_Override; } SourceLocation getOverrideLoc() const { return VS_overrideLoc; } - bool isFinalSpecified() const { return Specifiers & VS_Final; } + bool isFinalSpecified() const { return Specifiers & (VS_Final | VS_Sealed); } + bool isFinalSpelledSealed() const { return Specifiers & VS_Sealed; } SourceLocation getFinalLoc() const { return VS_finalLoc; } void clear() { Specifiers = 0; } Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Thu Oct 17 19:33:31 2013 @@ -1725,6 +1725,7 @@ public: /// member declarations. void ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagDecl, SourceLocation FinalLoc, + bool IsFinalSpelledSealed, SourceLocation LBraceLoc); /// ActOnTagFinishDefinition - Invoked once we have finished parsing Modified: cfe/trunk/lib/AST/StmtPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/lib/AST/StmtPrinter.cpp (original) +++ cfe/trunk/lib/AST/StmtPrinter.cpp Thu Oct 17 19:33:31 2013 @@ -1712,6 +1712,7 @@ static const char *getTypeTraitName(Unar case UTT_IsReference: return "__is_reference"; case UTT_IsRvalueReference: return "__is_rvalue_reference"; case UTT_IsScalar: return "__is_scalar"; + case UTT_IsSealed: return "__is_sealed"; case UTT_IsSigned: return "__is_signed"; case UTT_IsStandardLayout: return "__is_standard_layout"; case UTT_IsTrivial: return "__is_trivial"; Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original) +++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Thu Oct 17 19:33:31 2013 @@ -983,6 +983,7 @@ static bool HasFeature(const Preprocesso .Case("is_standard_layout", LangOpts.CPlusPlus) .Case("is_pod", LangOpts.CPlusPlus) .Case("is_polymorphic", LangOpts.CPlusPlus) + .Case("is_sealed", LangOpts.MicrosoftExt) .Case("is_trivial", LangOpts.CPlusPlus) .Case("is_trivially_assignable", LangOpts.CPlusPlus) .Case("is_trivially_constructible", LangOpts.CPlusPlus) Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Oct 17 19:33:31 2013 @@ -1837,12 +1837,17 @@ VirtSpecifiers::Specifier Parser::isCXX1 // Initialize the contextual keywords. if (!Ident_final) { Ident_final = &PP.getIdentifierTable().get("final"); + if (getLangOpts().MicrosoftExt) + Ident_sealed = &PP.getIdentifierTable().get("sealed"); Ident_override = &PP.getIdentifierTable().get("override"); } if (II == Ident_override) return VirtSpecifiers::VS_Override; + if (II == Ident_sealed) + return VirtSpecifiers::VS_Sealed; + if (II == Ident_final) return VirtSpecifiers::VS_Final; } @@ -1870,14 +1875,18 @@ void Parser::ParseOptionalCXX11VirtSpeci << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation()); - if (IsInterface && Specifier == VirtSpecifiers::VS_Final) { + if (IsInterface && (Specifier == VirtSpecifiers::VS_Final || + Specifier == VirtSpecifiers::VS_Sealed)) { Diag(Tok.getLocation(), diag::err_override_control_interface) << VirtSpecifiers::getSpecifierName(Specifier); + } else if (Specifier == VirtSpecifiers::VS_Sealed) { + Diag(Tok.getLocation(), diag::ext_ms_sealed_keyword); } else { - Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_override_control_keyword : - diag::ext_override_control_keyword) - << VirtSpecifiers::getSpecifierName(Specifier); + Diag(Tok.getLocation(), + getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_override_control_keyword + : diag::ext_override_control_keyword) + << VirtSpecifiers::getSpecifierName(Specifier); } ConsumeToken(); } @@ -1895,10 +1904,13 @@ bool Parser::isCXX11FinalKeyword() const // Initialize the contextual keywords. if (!Ident_final) { Ident_final = &PP.getIdentifierTable().get("final"); + if (getLangOpts().MicrosoftExt) + Ident_sealed = &PP.getIdentifierTable().get("sealed"); Ident_override = &PP.getIdentifierTable().get("override"); } - - return Tok.getIdentifierInfo() == Ident_final; + + return Tok.getIdentifierInfo() == Ident_final || + Tok.getIdentifierInfo() == Ident_sealed; } /// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration. @@ -1929,6 +1941,7 @@ bool Parser::isCXX11FinalKeyword() const /// virt-specifier: /// override /// final +/// [MS] sealed /// /// pure-specifier: /// '= 0' @@ -2520,20 +2533,27 @@ void Parser::ParseCXXMemberSpecification Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); SourceLocation FinalLoc; + bool IsFinalSpelledSealed = false; // Parse the optional 'final' keyword. if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) { - assert(isCXX11FinalKeyword() && "not a class definition"); + VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok); + assert((Specifier == VirtSpecifiers::VS_Final || + Specifier == VirtSpecifiers::VS_Sealed) && + "not a class definition"); FinalLoc = ConsumeToken(); + IsFinalSpelledSealed = Specifier == VirtSpecifiers::VS_Sealed; - if (TagType == DeclSpec::TST_interface) { + if (TagType == DeclSpec::TST_interface) Diag(FinalLoc, diag::err_override_control_interface) - << "final"; - } else { - Diag(FinalLoc, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_override_control_keyword : - diag::ext_override_control_keyword) << "final"; - } + << VirtSpecifiers::getSpecifierName(Specifier); + else if (Specifier == VirtSpecifiers::VS_Final) + Diag(FinalLoc, getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_override_control_keyword + : diag::ext_override_control_keyword) + << VirtSpecifiers::getSpecifierName(Specifier); + else if (Specifier == VirtSpecifiers::VS_Sealed) + Diag(FinalLoc, diag::ext_ms_sealed_keyword); // Parse any C++11 attributes after 'final' keyword. // These attributes are not allowed to appear here, @@ -2560,6 +2580,7 @@ void Parser::ParseCXXMemberSpecification if (TagDecl) Actions.ActOnStartCXXMemberDeclarations(getCurScope(), TagDecl, FinalLoc, + IsFinalSpelledSealed, T.getOpenLocation()); // C++ 11p3: Members of a class defined with the keyword class are private Modified: cfe/trunk/lib/Parse/ParseExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseExpr.cpp (original) +++ cfe/trunk/lib/Parse/ParseExpr.cpp Thu Oct 17 19:33:31 2013 @@ -591,6 +591,7 @@ class CastExpressionIdValidator : public /// '__is_final' /// '__is_pod' /// '__is_polymorphic' +/// '__is_sealed' [MS] /// '__is_trivial' /// '__is_union' /// @@ -1200,6 +1201,7 @@ ExprResult Parser::ParseCastExpression(b case tok::kw___is_trivially_copyable: case tok::kw___is_union: case tok::kw___is_final: + case tok::kw___is_sealed: case tok::kw___has_trivial_constructor: case tok::kw___has_trivial_move_constructor: case tok::kw___has_trivial_copy: Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Oct 17 19:33:31 2013 @@ -2669,6 +2669,7 @@ static UnaryTypeTrait UnaryTypeTraitFrom case tok::kw___is_reference: return UTT_IsReference; case tok::kw___is_rvalue_reference: return UTT_IsRvalueReference; case tok::kw___is_scalar: return UTT_IsScalar; + case tok::kw___is_sealed: return UTT_IsSealed; case tok::kw___is_signed: return UTT_IsSigned; case tok::kw___is_standard_layout: return UTT_IsStandardLayout; case tok::kw___is_trivial: return UTT_IsTrivial; Modified: cfe/trunk/lib/Parse/ParseTentative.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseTentative.cpp (original) +++ cfe/trunk/lib/Parse/ParseTentative.cpp Thu Oct 17 19:33:31 2013 @@ -962,6 +962,7 @@ Parser::isExpressionOrTypeSpecifierSimpl case tok::kw___is_literal_type: case tok::kw___is_pod: case tok::kw___is_polymorphic: + case tok::kw___is_sealed: case tok::kw___is_trivial: case tok::kw___is_trivially_assignable: case tok::kw___is_trivially_constructible: Modified: cfe/trunk/lib/Parse/Parser.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/lib/Parse/Parser.cpp (original) +++ cfe/trunk/lib/Parse/Parser.cpp Thu Oct 17 19:33:31 2013 @@ -486,6 +486,7 @@ void Parser::Initialize() { Ident_instancetype = 0; Ident_final = 0; + Ident_sealed = 0; Ident_override = 0; Ident_super = &PP.getIdentifierTable().get("super"); Modified: cfe/trunk/lib/Sema/DeclSpec.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/lib/Sema/DeclSpec.cpp (original) +++ cfe/trunk/lib/Sema/DeclSpec.cpp Thu Oct 17 19:33:31 2013 @@ -1118,6 +1118,7 @@ bool VirtSpecifiers::SetSpecifier(Specif 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::getSpecifier default: llvm_unreachable("Unknown specifier"); case VS_Override: return "override"; case VS_Final: return "final"; + case VS_Sealed: return "sealed"; } } Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Oct 17 19:33:31 2013 @@ -10957,6 +10957,7 @@ Decl *Sema::ActOnObjCContainerStartDefin 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::ActOnStartCXXMemberDeclaratio 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 Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Oct 17 19:33:31 2013 @@ -1373,9 +1373,10 @@ Sema::CheckBaseSpecifier(CXXRecordDecl * // 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(NamedDec } 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(NamedDec 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(NamedDec /// 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, 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(CXXRec 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()) { Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Oct 17 19:33:31 2013 @@ -3131,6 +3131,7 @@ static bool CheckUnaryTypeTraitTypeCompl // 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 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: Modified: cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp (original) +++ cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp Thu Oct 17 19:33:31 2013 @@ -385,3 +385,28 @@ namespace rdar14250378 { } } } + +// expected-error@+1 {{'sealed' keyword not permitted with interface types}} +__interface InterfaceWithSealed sealed { +}; + +struct SomeBase { + virtual void OverrideMe(); + + // expected-note@+2 {{overridden virtual function is here}} + // expected-warning@+1 {{'sealed' keyword is a Microsoft extension}} + virtual void SealedFunction() sealed; +}; + +// expected-note@+2 {{'SealedType' declared here}} +// expected-warning@+1 {{'sealed' keyword is a Microsoft extension}} +struct SealedType sealed : SomeBase { + // expected-error@+1 {{declaration of 'SealedFunction' overrides a 'sealed' function}} + virtual void SealedFunction(); + + // expected-warning@+1 {{'override' keyword is a C++11 extension}} + virtual void OverrideMe() override; +}; + +// expected-error@+1 {{base 'SealedType' is marked 'sealed'}} +struct InheritFromSealed : SealedType {}; Modified: cfe/trunk/test/SemaCXX/type-traits.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=192936&r1=192935&r2=192936&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/type-traits.cpp (original) +++ cfe/trunk/test/SemaCXX/type-traits.cpp Thu Oct 17 19:33:31 2013 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 -fms-extensions -Wno-microsoft %s #define T(b) (b) ? 1 : -1 #define F(b) (b) ? -1 : 1 @@ -308,6 +308,37 @@ void is_final() { int arr[F(__is_final(PotentiallyFinal<float>))]; } } +struct SealedClass sealed { +}; + +template<typename T> +struct PotentiallySealed { }; + +template<typename T> +struct PotentiallySealed<T*> sealed { }; + +template<> +struct PotentiallySealed<int> sealed { }; + +void is_sealed() +{ + { int arr[T(__is_sealed(SealedClass))]; } + { int arr[T(__is_sealed(PotentiallySealed<float*>))]; } + { int arr[T(__is_sealed(PotentiallySealed<int>))]; } + + { int arr[F(__is_sealed(int))]; } + { int arr[F(__is_sealed(Union))]; } + { int arr[F(__is_sealed(Int))]; } + { int arr[F(__is_sealed(IntAr))]; } + { int arr[F(__is_sealed(UnionAr))]; } + { int arr[F(__is_sealed(Derives))]; } + { int arr[F(__is_sealed(ClassType))]; } + { int arr[F(__is_sealed(cvoid))]; } + { int arr[F(__is_sealed(IntArNB))]; } + { int arr[F(__is_sealed(HasAnonymousUnion))]; } + { int arr[F(__is_sealed(PotentiallyFinal<float>))]; } +} + typedef HasVirt Polymorph; struct InheritPolymorph : Polymorph {}; _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
