From: Anders Carlsson Date: Sun, 23 Jan 2011 21:07:30 +0000 (+0000) Subject: Get rid of the [[final]] C++0x attribute. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f89e0424b8903438179f4a2f16dddd5e5bdc814e;p=clang Get rid of the [[final]] C++0x attribute. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124083 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index d3039d2c17..38c67b2964 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -223,12 +223,6 @@ def FastCall : InheritableAttr { let Spellings = ["fastcall", "__fastcall"]; } -def Final : InheritableAttr { - let Spellings = ["final"]; - let Subjects = [CXXRecord, CXXVirtualMethod]; - let Namespaces = ["", "std"]; -} - def Format : InheritableAttr { let Spellings = ["format"]; let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">, diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index c3e1aead2b..99005e38e4 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -104,7 +104,6 @@ public: AT_dllimport, AT_ext_vector_type, AT_fastcall, - AT_final, AT_format, AT_format_arg, AT_global, diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 5521c0f8ce..9ce90c0ce8 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -63,14 +63,14 @@ static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context, if (Context.getLangOptions().AppleKext) return false; - // If the member function has the "final" attribute, we know that it can't be + // If the member function is marked 'final', we know that it can't be // overridden and can therefore devirtualize it. - if (MD->hasAttr()) + if (MD->isMarkedFinal()) return true; - // Similarly, if the class itself has the "final" attribute it can't be - // overridden and we can therefore devirtualize the member function call. - if (MD->getParent()->hasAttr()) + // 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()) return true; if (const DeclRefExpr *DRE = dyn_cast(Base)) { diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 4d16f033be..44c6921715 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -2223,7 +2223,6 @@ void Parser::ParseCXX0XAttributes(ParsedAttributesWithRange &attrs, // No arguments case AttributeList::AT_base_check: case AttributeList::AT_carries_dependency: - case AttributeList::AT_final: case AttributeList::AT_hiding: case AttributeList::AT_noreturn: case AttributeList::AT_override: { diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp index 6e0a332104..d8d0c7b1a7 100644 --- a/lib/Sema/AttributeList.cpp +++ b/lib/Sema/AttributeList.cpp @@ -51,7 +51,6 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("used", AT_used) .Case("alias", AT_alias) .Case("align", AT_aligned) - .Case("final", AT_final) .Case("cdecl", AT_cdecl) .Case("const", AT_const) .Case("__const", AT_const) // some GCC headers do contain this spelling diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 9c9846ebf5..88afaf30b7 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2437,32 +2437,6 @@ static void HandleLaunchBoundsAttr(Decl *d, const AttributeList &Attr, Sema &S){ } } -static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) { - // check the attribute arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; - } - - if (!isa(d) - && (!isa(d) || !cast(d)->isVirtual())) { - S.Diag(Attr.getLoc(), - Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type - : diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 7 /*virtual method or class*/; - return; - } - - // FIXME: Conform to C++0x redeclaration rules. - - if (d->getAttr()) { - S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "final"; - return; - } - - d->addAttr(::new (S.Context) FinalAttr(Attr.getLoc(), S.Context)); -} - //===----------------------------------------------------------------------===// // C++0x member checking attributes //===----------------------------------------------------------------------===// @@ -2632,11 +2606,11 @@ static void HandleUuidAttr(Decl *d, const AttributeList &Attr, Sema &S) { // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" - llvm::StringRef::iterator I = StrRef.begin(); - if (IsCurly) // Skip the optional '{' - ++I; - - for (int i = 0; i < 36; ++i) { + llvm::StringRef::iterator I = StrRef.begin(); + if (IsCurly) // Skip the optional '{' + ++I; + + for (int i = 0; i < 36; ++i) { if (i == 8 || i == 13 || i == 18 || i == 23) { if (*I != '-') { S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); @@ -2709,7 +2683,6 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, case AttributeList::AT_ext_vector_type: HandleExtVectorTypeAttr(scope, D, Attr, S); break; - case AttributeList::AT_final: HandleFinalAttr (D, Attr, S); break; case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break; case AttributeList::AT_global: HandleGlobalAttr (D, Attr, S); break; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 9def74d954..eeb665b61d 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -533,15 +533,6 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, return 0; } - // FIXME: Get rid of this. - // C++0x CWG Issue #817 indicates that [[final]] classes shouldn't be bases. - if (CXXBaseDecl->hasAttr()) { - Diag(BaseLoc, diag::err_final_base) << BaseType.getAsString(); - Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl) - << BaseType; - return 0; - } - if (BaseDecl->isInvalidDecl()) Class->setInvalidDecl(); @@ -913,15 +904,13 @@ void Sema::CheckOverrideControl(const Decl *D) { /// C++0x [class.virtual]p3. bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, const CXXMethodDecl *Old) { - // FIXME: Get rid of FinalAttr here. - if (Old->hasAttr() || Old->isMarkedFinal()) { - Diag(New->getLocation(), diag::err_final_function_overridden) - << New->getDeclName(); - Diag(Old->getLocation(), diag::note_overridden_virtual_function); - return true; - } - - return false; + if (!Old->isMarkedFinal()) + return false; + + Diag(New->getLocation(), diag::err_final_function_overridden) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; } /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.final/p4.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.final/p4.cpp deleted file mode 100644 index cac362409a..0000000000 --- a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.final/p4.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s - -struct B1 { - [[final]] virtual void f(); // expected-note {{overridden virtual function is here}} -}; - -struct D1 : B1 { - void f(); // expected-error {{declaration of 'f' overrides a 'final' function}} -}; - -struct [[final]] B2 { // expected-note {{'B2' declared here}} -}; - -struct D2 : B2 { // expected-error {{derivation from 'final' struct B2}} -}; diff --git a/test/CodeGenCXX/attr-final-devirtualize-virtual-function-calls.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp similarity index 50% rename from test/CodeGenCXX/attr-final-devirtualize-virtual-function-calls.cpp rename to test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp index a45078055d..f6f2a49133 100644 --- a/test/CodeGenCXX/attr-final-devirtualize-virtual-function-calls.cpp +++ b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp @@ -1,25 +1,25 @@ -// RUN: %clang_cc1 %s -O3 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s namespace Test1 { struct A { - virtual int f() __attribute__((final)) { return 1; } + virtual int f() final; }; // CHECK: define i32 @_ZN5Test11fEPNS_1AE int f(A *a) { - // CHECK: ret i32 1 + // CHECK: call i32 @_ZN5Test11A1fEv return a->f(); } } namespace Test2 { - struct __attribute__((final)) A { - virtual int f() { return 1; } + struct A final { + virtual int f(); }; // CHECK: define i32 @_ZN5Test21fEPNS_1AE int f(A *a) { - // CHECK: ret i32 1 + // CHECK: call i32 @_ZN5Test21A1fEv return a->f(); } } diff --git a/test/Parser/cxx0x-attributes.cpp b/test/Parser/cxx0x-attributes.cpp index 67b2ea6f62..9956427ebf 100644 --- a/test/Parser/cxx0x-attributes.cpp +++ b/test/Parser/cxx0x-attributes.cpp @@ -29,7 +29,6 @@ extern "C++" [[]] { } // expected-error {{an attribute list cannot appear here}} [[]] using namespace ns; // Argument tests -[[final()]] int final_params; // expected-error {{C++0x attribute 'final' cannot have an argument list}} [[align]] int aligned_no_params; // expected-error {{C++0x attribute 'align' must have an argument list}} [[align(i)]] int aligned_nonconst; // expected-error {{'aligned' attribute requires integer constant}} diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp index 4d1e47f7c3..5570f672cc 100644 --- a/test/SemaCXX/attr-cxx0x.cpp +++ b/test/SemaCXX/attr-cxx0x.cpp @@ -1,13 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s -int final_fail [[final]]; //expected-error {{'final' attribute only applies to virtual method or class types}} - -struct [[final]] final_base { }; // expected-note {{'final_base' declared here}} -struct final_child : final_base { }; // expected-error {{derivation from 'final' struct final_base}} - -struct final_member { virtual void quux [[final]] (); }; // expected-note {{overridden virtual function is here}} -struct final_override : final_member { virtual void quux (); }; // expected-error {{declaration of 'quux' overrides a 'final' function}} - int align_illegal [[align(3)]]; //expected-error {{requested alignment is not a power of 2}} char align_big [[align(int)]]; int align_small [[align(1)]]; // FIXME: this should be rejected