r192936 - [-fms-extensions] Permit 'override' in C++98 and 'sealed' as a synonym for 'final'
David Majnemer
david.majnemer at gmail.com
Thu Oct 17 17:33:31 PDT 2013
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 at +1 {{'sealed' keyword not permitted with interface types}}
+__interface InterfaceWithSealed sealed {
+};
+
+struct SomeBase {
+ virtual void OverrideMe();
+
+ // expected-note at +2 {{overridden virtual function is here}}
+ // expected-warning at +1 {{'sealed' keyword is a Microsoft extension}}
+ virtual void SealedFunction() sealed;
+};
+
+// expected-note at +2 {{'SealedType' declared here}}
+// expected-warning at +1 {{'sealed' keyword is a Microsoft extension}}
+struct SealedType sealed : SomeBase {
+ // expected-error at +1 {{declaration of 'SealedFunction' overrides a 'sealed' function}}
+ virtual void SealedFunction();
+
+ // expected-warning at +1 {{'override' keyword is a C++11 extension}}
+ virtual void OverrideMe() override;
+};
+
+// expected-error at +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 {};
More information about the cfe-commits
mailing list