aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hunt <rideau3@gmail.com>2009-11-25 04:20:27 +0000
committerSean Hunt <rideau3@gmail.com>2009-11-25 04:20:27 +0000
commit7725e67639fa2fe74f8775b7ed884a076ffdbffc (patch)
treeb518c376db3544834ecabb7afdd3b82554a6a83e
parent717a5955e93aa7ecf1b8878a9f2c90ead9a71c38 (diff)
Parse C++ member check attributes - base_check, hiding, and override.
The attributes are currently ignored. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89837 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Attr.h8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td9
-rw-r--r--include/clang/Parse/AttributeList.h3
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp3
-rw-r--r--lib/Frontend/PCHWriter.cpp5
-rw-r--r--lib/Parse/AttributeList.cpp13
-rw-r--r--lib/Parse/ParseDeclCXX.cpp7
-rw-r--r--lib/Sema/SemaDeclAttr.cpp168
-rw-r--r--test/SemaCXX/attr-cxx0x.cpp12
9 files changed, 176 insertions, 52 deletions
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 35f9b330dd..f8c2aa9c69 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -49,6 +49,7 @@ public:
AnalyzerNoReturn, // Clang-specific.
Annotate,
AsmLabel, // Represent GCC asm label extension.
+ BaseCheck,
Blocks,
CDecl,
Cleanup,
@@ -63,6 +64,7 @@ public:
Format,
FormatArg,
GNUInline,
+ Hiding,
IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict with
Malloc,
NoDebug,
@@ -72,6 +74,7 @@ public:
NoThrow,
ObjCException,
ObjCNSObject,
+ Override,
CFReturnsRetained, // Clang/Checker-specific.
NSReturnsRetained, // Clang/Checker-specific.
Overloadable, // Clang-specific
@@ -558,6 +561,11 @@ public:
DEF_SIMPLE_ATTR(CFReturnsRetained);
DEF_SIMPLE_ATTR(NSReturnsRetained);
+// C++0x member checking attributes.
+DEF_SIMPLE_ATTR(BaseCheck);
+DEF_SIMPLE_ATTR(Hiding);
+DEF_SIMPLE_ATTR(Override);
+
#undef DEF_SIMPLE_ATTR
} // end namespace clang
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index c3b504592f..69a22b504a 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -551,6 +551,9 @@ def err_auto_not_allowed : Error<
"|class member|exception declaration|template parameter|block literal}0">;
def err_auto_var_requires_init : Error<
"declaration of variable %0 with type %1 requires an initializer">;
+
+// C++0x attributes
+def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">;
// C++0x [[final]]
def err_final_function_overridden : Error<
@@ -646,12 +649,14 @@ def warn_attribute_wrong_decl_type : Warning<
"%0 attribute only applies to %select{function|union|"
"variable and function|function or method|parameter|"
"parameter or Objective-C method |function, method or block|"
- "virtual method or class|function, method, or parameter}1 types">;
+ "virtual method or class|function, method, or parameter|class|virtual method"
+ "|member}1 types">;
def err_attribute_wrong_decl_type : Error<
"%0 attribute only applies to %select{function|union|"
"variable and function|function or method|parameter|"
"parameter or Objective-C method |function, method or block|"
- "virtual method or class|function, method, or parameter}1 types">;
+ "virtual method or class|function, method, or parameter|class|virtual method"
+ "|member}1 types">;
def warn_gnu_inline_attribute_requires_inline : Warning<
"'gnu_inline' attribute requires function to be marked 'inline',"
" attribute ignored">;
diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h
index e273cadff1..ecaa6aee47 100644
--- a/include/clang/Parse/AttributeList.h
+++ b/include/clang/Parse/AttributeList.h
@@ -59,6 +59,7 @@ public:
AT_always_inline,
AT_analyzer_noreturn,
AT_annotate,
+ AT_base_check,
AT_blocks,
AT_carries_dependency,
AT_cdecl,
@@ -75,6 +76,7 @@ public:
AT_format,
AT_format_arg,
AT_gnu_inline,
+ AT_hiding,
AT_malloc,
AT_mode,
AT_nodebug,
@@ -85,6 +87,7 @@ public:
AT_nothrow,
AT_nsobject,
AT_objc_exception,
+ AT_override,
AT_cf_returns_retained, // Clang-specific.
AT_ns_returns_retained, // Clang-specific.
AT_objc_gc,
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index 328bb611ba..03f3b47679 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -441,6 +441,7 @@ Attr *PCHReader::ReadAttributes() {
SIMPLE_ATTR(AnalyzerNoReturn);
STRING_ATTR(Annotate);
STRING_ATTR(AsmLabel);
+ SIMPLE_ATTR(BaseCheck);
case Attr::Blocks:
New = ::new (*Context) BlocksAttr(
@@ -485,6 +486,7 @@ Attr *PCHReader::ReadAttributes() {
}
SIMPLE_ATTR(GNUInline);
+ SIMPLE_ATTR(Hiding);
case Attr::IBOutletKind:
New = ::new (*Context) IBOutletAttr();
@@ -518,6 +520,7 @@ Attr *PCHReader::ReadAttributes() {
SIMPLE_ATTR(CFReturnsRetained);
SIMPLE_ATTR(NSReturnsRetained);
SIMPLE_ATTR(Overloadable);
+ SIMPLE_ATTR(Override);
SIMPLE_ATTR(Packed);
UNSIGNED_ATTR(PragmaPack);
SIMPLE_ATTR(Pure);
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index d60af61bd8..06727c4a50 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -1764,6 +1764,9 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
AddString(cast<AsmLabelAttr>(Attr)->getLabel(), Record);
break;
+ case Attr::BaseCheck:
+ break;
+
case Attr::Blocks:
Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable
break;
@@ -1817,6 +1820,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
}
case Attr::GNUInline:
+ case Attr::Hiding:
case Attr::IBOutletKind:
case Attr::Malloc:
case Attr::NoDebug:
@@ -1837,6 +1841,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
case Attr::CFReturnsRetained:
case Attr::NSReturnsRetained:
case Attr::Overloadable:
+ case Attr::Override:
break;
case Attr::PragmaPack:
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index 7e2935c2e0..df48e3a786 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -65,11 +65,12 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("final", AT_final)
.Case("cdecl", AT_cdecl)
.Case("const", AT_const)
- .Case("packed", AT_packed)
- .Case("malloc", AT_malloc)
+ .Case("blocks", AT_blocks)
.Case("format", AT_format)
+ .Case("hiding", AT_hiding)
+ .Case("malloc", AT_malloc)
+ .Case("packed", AT_packed)
.Case("unused", AT_unused)
- .Case("blocks", AT_blocks)
.Case("aligned", AT_aligned)
.Case("cleanup", AT_cleanup)
.Case("nodebug", AT_nodebug)
@@ -80,15 +81,17 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("section", AT_section)
.Case("stdcall", AT_stdcall)
.Case("annotate", AT_annotate)
- .Case("noreturn", AT_noreturn)
- .Case("noinline", AT_noinline)
.Case("fastcall", AT_fastcall)
.Case("iboutlet", AT_IBOutlet)
+ .Case("noreturn", AT_noreturn)
+ .Case("noinline", AT_noinline)
+ .Case("override", AT_override)
.Case("sentinel", AT_sentinel)
.Case("NSObject", AT_nsobject)
.Case("dllimport", AT_dllimport)
.Case("dllexport", AT_dllexport)
.Case("may_alias", IgnoredAttribute) // FIXME: TBAA
+ .Case("base_check", AT_base_check)
.Case("deprecated", AT_deprecated)
.Case("visibility", AT_visibility)
.Case("destructor", AT_destructor)
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 2a3b5d665c..59cb90d6d0 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1699,9 +1699,12 @@ CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) {
switch(AttributeList::getKind(AttrName))
{
// No arguments
- case AttributeList::AT_noreturn:
+ case AttributeList::AT_base_check:
+ case AttributeList::AT_carries_dependency:
case AttributeList::AT_final:
- case AttributeList::AT_carries_dependency: {
+ case AttributeList::AT_hiding:
+ case AttributeList::AT_noreturn:
+ case AttributeList::AT_override: {
if (Tok.is(tok::l_paren)) {
Diag(Tok.getLocation(), diag::err_cxx0x_attribute_forbids_arguments)
<< AttrName->getName();
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 2405d52890..f40f125683 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1825,15 +1825,94 @@ static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
<< Attr.getName() << 7 /*virtual method or class*/;
return;
}
-
- // FIXME: Check that it's not specified more than once in an attribute-
- // specifier and that it conforms to the C++0x rules for
- // redeclarations.
+
+ // 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());
}
//===----------------------------------------------------------------------===//
+// C++0x member checking attributes
+//===----------------------------------------------------------------------===//
+
+static void HandleBaseCheckAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<CXXRecordDecl>(d)) {
+ S.Diag(Attr.getLoc(),
+ Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+ : diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 9 /*class*/;
+ return;
+ }
+
+ if (d->getAttr<BaseCheckAttr>()) {
+ S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "base_check";
+ return;
+ }
+
+ d->addAttr(::new (S.Context) BaseCheckAttr());
+}
+
+static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<RecordDecl>(d->getDeclContext())) {
+ // FIXME: It's not the type that's the problem
+ S.Diag(Attr.getLoc(),
+ Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+ : diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 11 /*member*/;
+ return;
+ }
+
+ // FIXME: Conform to C++0x redeclaration rules.
+
+ if (d->getAttr<HidingAttr>()) {
+ S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "hiding";
+ return;
+ }
+
+ d->addAttr(::new (S.Context) HidingAttr());
+}
+
+static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<CXXMethodDecl>(d) || !cast<CXXMethodDecl>(d)->isVirtual()) {
+ // FIXME: It's not the type that's the problem
+ S.Diag(Attr.getLoc(),
+ Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+ : diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 10 /*virtual method*/;
+ return;
+ }
+
+ // FIXME: Conform to C++0x redeclaration rules.
+
+ if (d->getAttr<OverrideAttr>()) {
+ S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "override";
+ return;
+ }
+
+ d->addAttr(::new (S.Context) OverrideAttr());
+}
+
+//===----------------------------------------------------------------------===//
// Checker-specific attribute handlers.
//===----------------------------------------------------------------------===//
@@ -1894,34 +1973,37 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
// Ignore these, these are type attributes, handled by
// ProcessTypeAttributes.
break;
- case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break;
- case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break;
+ case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break;
+ case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break;
case AttributeList::AT_always_inline:
HandleAlwaysInlineAttr (D, Attr, S); break;
case AttributeList::AT_analyzer_noreturn:
HandleAnalyzerNoReturnAttr (D, Attr, S); break;
- case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
+ case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
+ case AttributeList::AT_base_check: HandleBaseCheckAttr (D, Attr, S); break;
case AttributeList::AT_carries_dependency:
- HandleDependencyAttr (D, Attr, S); break;
- case AttributeList::AT_cdecl: HandleCDeclAttr (D, Attr, S); break;
- case AttributeList::AT_constructor: HandleConstructorAttr(D, Attr, S); break;
- case AttributeList::AT_deprecated: HandleDeprecatedAttr(D, Attr, S); break;
- case AttributeList::AT_destructor: HandleDestructorAttr(D, Attr, S); break;
- case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break;
- case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break;
+ HandleDependencyAttr (D, Attr, S); break;
+ case AttributeList::AT_cdecl: HandleCDeclAttr (D, Attr, S); break;
+ case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break;
+ case AttributeList::AT_deprecated: HandleDeprecatedAttr (D, Attr, S); break;
+ case AttributeList::AT_destructor: HandleDestructorAttr (D, Attr, S); break;
+ case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break;
+ case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break;
case AttributeList::AT_ext_vector_type:
HandleExtVectorTypeAttr(scope, D, Attr, S);
break;
- case AttributeList::AT_fastcall: HandleFastCallAttr (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_gnu_inline: HandleGNUInlineAttr (D, Attr, S); break;
- case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break;
- case AttributeList::AT_malloc: HandleMallocAttr (D, Attr, S); break;
- case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break;
- case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break;
- case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break;
+ case AttributeList::AT_fastcall: HandleFastCallAttr (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_gnu_inline: HandleGNUInlineAttr (D, Attr, S); break;
+ case AttributeList::AT_hiding: HandleHidingAttr (D, Attr, S); break;
+ case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break;
+ case AttributeList::AT_malloc: HandleMallocAttr (D, Attr, S); break;
+ case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break;
+ case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break;
+ case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break;
+ case AttributeList::AT_override: HandleOverrideAttr (D, Attr, S); break;
// Checker-specific.
case AttributeList::AT_ns_returns_retained:
@@ -1931,18 +2013,18 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
case AttributeList::AT_reqd_wg_size:
HandleReqdWorkGroupSize(D, Attr, S); break;
- case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break;
- case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break;
- case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break;
- case AttributeList::AT_unavailable: HandleUnavailableAttr(D, Attr, S); break;
- case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break;
- case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break;
- case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break;
- case AttributeList::AT_visibility: HandleVisibilityAttr(D, Attr, S); break;
+ case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break;
+ case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break;
+ case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break;
+ case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break;
+ case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break;
+ case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break;
+ case AttributeList::AT_vector_size: HandleVectorSizeAttr (D, Attr, S); break;
+ case AttributeList::AT_visibility: HandleVisibilityAttr (D, Attr, S); break;
case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S);
break;
- case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break;
- case AttributeList::AT_weak_import: HandleWeakImportAttr(D, Attr, S); break;
+ case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break;
+ case AttributeList::AT_weak_import: HandleWeakImportAttr (D, Attr, S); break;
case AttributeList::AT_transparent_union:
HandleTransparentUnionAttr(D, Attr, S);
break;
@@ -1950,15 +2032,15 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
HandleObjCExceptionAttr(D, Attr, S);
break;
case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break;
- case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break;
- case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break;
- case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break;
- case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break;
- case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break;
- case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break;
- case AttributeList::AT_nodebug: HandleNoDebugAttr (D, Attr, S); break;
- case AttributeList::AT_noinline: HandleNoInlineAttr (D, Attr, S); break;
- case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break;
+ case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break;
+ case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break;
+ case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break;
+ case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break;
+ case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break;
+ case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break;
+ case AttributeList::AT_nodebug: HandleNoDebugAttr (D, Attr, S); break;
+ case AttributeList::AT_noinline: HandleNoInlineAttr (D, Attr, S); break;
+ case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break;
case AttributeList::IgnoredAttribute:
case AttributeList::AT_no_instrument_function: // Interacts with -pg.
// Just ignore
diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp
index fed0ad42d8..da52d338cf 100644
--- a/test/SemaCXX/attr-cxx0x.cpp
+++ b/test/SemaCXX/attr-cxx0x.cpp
@@ -22,3 +22,15 @@ static_assert(alignof(align_small) == alignof(int), "j's alignment is wrong");
static_assert(alignof(align_multiple) == 8, "l's alignment is wrong");
static_assert(alignof(align_member) == 8, "quuux's alignment is wrong");
static_assert(sizeof(align_member) == 8, "quuux's size is wrong");
+
+int bc_fail [[base_check]]; // expected-error {{'base_check' attribute only applies to class types}}
+int hiding_fail [[hiding]]; // expected-error {{'hiding' attribute only applies to member types}}
+int override_fail [[override]]; // expected-error {{'override' attribute only applies to virtual method types}}
+
+struct base {
+ virtual void function();
+ virtual void other_function();
+};
+
+struct [[base_check, base_check]] bc : base { // expected-error {{'base_check' attribute cannot be repeated}}
+}; \ No newline at end of file