aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/Attr.td6
-rw-r--r--include/clang/Sema/AttributeList.h1
-rw-r--r--lib/CodeGen/CGExprCXX.cpp10
-rw-r--r--lib/Parse/ParseDeclCXX.cpp1
-rw-r--r--lib/Sema/AttributeList.cpp1
-rw-r--r--lib/Sema/SemaDeclAttr.cpp37
-rw-r--r--lib/Sema/SemaDeclCXX.cpp25
-rw-r--r--test/CXX/dcl.dcl/dcl.attr/dcl.attr.final/p4.cpp15
-rw-r--r--test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp (renamed from test/CodeGenCXX/attr-final-devirtualize-virtual-function-calls.cpp)12
-rw-r--r--test/Parser/cxx0x-attributes.cpp1
-rw-r--r--test/SemaCXX/attr-cxx0x.cpp8
11 files changed, 23 insertions, 94 deletions
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<FinalAttr>())
+ 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<FinalAttr>())
+ // 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<DeclRefExpr>(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<CXXRecordDecl>(d)
- && (!isa<CXXMethodDecl>(d) || !cast<CXXMethodDecl>(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<FinalAttr>()) {
- 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<FinalAttr>()) {
- 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<FinalAttr>() || 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
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