Parse C++ member check attributes - base_check, hiding, and override.

The attributes are currently ignored.

llvm-svn: 89837
This commit is contained in:
Alexis Hunt 2009-11-25 04:20:27 +00:00
parent ddeb7e09cb
commit 54a0254887
9 changed files with 177 additions and 53 deletions

View File

@ -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

View File

@ -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">;

View File

@ -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,

View File

@ -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);

View File

@ -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:

View File

@ -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("format", AT_format)
.Case("unused", AT_unused)
.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("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)

View File

@ -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();

View File

@ -1825,14 +1825,93 @@ 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

View File

@ -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}}
};