forked from OSchip/llvm-project
[-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 llvm-svn: 192936
This commit is contained in:
parent
6939177cea
commit
a543308ce5
clang
include/clang
Basic
Parse
Sema
lib
AST
Lex
Parse
Sema
test/SemaCXX
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -704,6 +704,9 @@ def warn_cxx98_compat_override_control_keyword : Warning<
|
|||
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">;
|
||||
|
|
|
@ -1552,16 +1552,16 @@ def override_keyword_hides_virtual_member_function : Error<
|
|||
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<
|
||||
|
|
|
@ -350,6 +350,7 @@ KEYWORD(typeof , KEYGNU)
|
|||
|
||||
// MS Extensions
|
||||
KEYWORD(L__FUNCTION__ , KEYMS)
|
||||
KEYWORD(__is_sealed , KEYMS)
|
||||
|
||||
// GNU and MS Type Traits
|
||||
KEYWORD(__has_nothrow_assign , KEYCXX)
|
||||
|
|
|
@ -57,6 +57,7 @@ namespace clang {
|
|||
UTT_IsReference,
|
||||
UTT_IsRvalueReference,
|
||||
UTT_IsScalar,
|
||||
UTT_IsSealed,
|
||||
UTT_IsSigned,
|
||||
UTT_IsStandardLayout,
|
||||
UTT_IsTrivial,
|
||||
|
|
|
@ -102,6 +102,7 @@ class Parser : public CodeCompletionHandler {
|
|||
|
||||
/// Contextual keywords for Microsoft extensions.
|
||||
IdentifierInfo *Ident__except;
|
||||
mutable IdentifierInfo *Ident_sealed;
|
||||
|
||||
/// Ident_super - IdentifierInfo for "super", to support fast
|
||||
/// comparison.
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1712,6 +1712,7 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) {
|
|||
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";
|
||||
|
|
|
@ -983,6 +983,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
|
|||
.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)
|
||||
|
|
|
@ -1837,12 +1837,17 @@ VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) 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");
|
||||
}
|
||||
|
||||
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::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS,
|
|||
<< 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(SourceLocation RecordLoc,
|
|||
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(SourceLocation RecordLoc,
|
|||
|
||||
if (TagDecl)
|
||||
Actions.ActOnStartCXXMemberDeclarations(getCurScope(), TagDecl, FinalLoc,
|
||||
IsFinalSpelledSealed,
|
||||
T.getOpenLocation());
|
||||
|
||||
// C++ 11p3: Members of a class defined with the keyword class are private
|
||||
|
|
|
@ -591,6 +591,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
|
|||
/// '__is_final'
|
||||
/// '__is_pod'
|
||||
/// '__is_polymorphic'
|
||||
/// '__is_sealed' [MS]
|
||||
/// '__is_trivial'
|
||||
/// '__is_union'
|
||||
///
|
||||
|
@ -1200,6 +1201,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
|||
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:
|
||||
|
|
|
@ -2669,6 +2669,7 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
|
|||
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;
|
||||
|
|
|
@ -962,6 +962,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
|
|||
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:
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 {};
|
||||
|
|
|
@ -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 {};
|
||||
|
||||
|
|
Loading…
Reference in New Issue