forked from OSchip/llvm-project
Allow for annotate attributes after access specifiers. When such
attributes are found, propagate them to subsequent declarations. llvm-svn: 141861
This commit is contained in:
parent
25f6d3e321
commit
ca98f2a63f
|
@ -1830,7 +1830,8 @@ enum CXCursorKind {
|
||||||
CXCursor_IBOutletCollectionAttr = 403,
|
CXCursor_IBOutletCollectionAttr = 403,
|
||||||
CXCursor_CXXFinalAttr = 404,
|
CXCursor_CXXFinalAttr = 404,
|
||||||
CXCursor_CXXOverrideAttr = 405,
|
CXCursor_CXXOverrideAttr = 405,
|
||||||
CXCursor_LastAttr = CXCursor_CXXOverrideAttr,
|
CXCursor_AnnotateAttr = 406,
|
||||||
|
CXCursor_LastAttr = CXCursor_AnnotateAttr,
|
||||||
|
|
||||||
/* Preprocessing */
|
/* Preprocessing */
|
||||||
CXCursor_PreprocessingDirective = 500,
|
CXCursor_PreprocessingDirective = 500,
|
||||||
|
|
|
@ -1365,6 +1365,8 @@ def err_attr_objc_ownership_redundant : Error<
|
||||||
"the type %0 already has retainment attributes set on it">;
|
"the type %0 already has retainment attributes set on it">;
|
||||||
def err_attribute_not_string : Error<
|
def err_attribute_not_string : Error<
|
||||||
"argument to %0 attribute was not a string literal">;
|
"argument to %0 attribute was not a string literal">;
|
||||||
|
def err_only_annotate_after_access_spec : Error<
|
||||||
|
"access specifier can only have annotation attributes">;
|
||||||
def err_attribute_section_invalid_for_target : Error<
|
def err_attribute_section_invalid_for_target : Error<
|
||||||
"argument to 'section' attribute is not valid for this target: %0">;
|
"argument to 'section' attribute is not valid for this target: %0">;
|
||||||
def err_attribute_section_local_variable : Error<
|
def err_attribute_section_local_variable : Error<
|
||||||
|
|
|
@ -1125,7 +1125,8 @@ private:
|
||||||
void DeallocateParsedClasses(ParsingClass *Class);
|
void DeallocateParsedClasses(ParsingClass *Class);
|
||||||
void PopParsingClass(Sema::ParsingClassState);
|
void PopParsingClass(Sema::ParsingClassState);
|
||||||
|
|
||||||
Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
|
Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, AttributeList *AccessAttrs,
|
||||||
|
ParsingDeclarator &D,
|
||||||
const ParsedTemplateInfo &TemplateInfo,
|
const ParsedTemplateInfo &TemplateInfo,
|
||||||
const VirtSpecifiers& VS, ExprResult& Init);
|
const VirtSpecifiers& VS, ExprResult& Init);
|
||||||
void ParseCXXNonStaticMemberInitializer(Decl *VarD);
|
void ParseCXXNonStaticMemberInitializer(Decl *VarD);
|
||||||
|
@ -1961,7 +1962,7 @@ private:
|
||||||
Decl *TagDecl);
|
Decl *TagDecl);
|
||||||
ExprResult ParseCXXMemberInitializer(bool IsFunction,
|
ExprResult ParseCXXMemberInitializer(bool IsFunction,
|
||||||
SourceLocation &EqualLoc);
|
SourceLocation &EqualLoc);
|
||||||
void ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
void ParseCXXClassMemberDeclaration(AccessSpecifier AS, AttributeList *Attr,
|
||||||
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
|
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
|
||||||
ParsingDeclRAIIObject *DiagsFromTParams = 0);
|
ParsingDeclRAIIObject *DiagsFromTParams = 0);
|
||||||
void ParseConstructorInitializer(Decl *ConstructorDecl);
|
void ParseConstructorInitializer(Decl *ConstructorDecl);
|
||||||
|
@ -1998,16 +1999,19 @@ private:
|
||||||
// C++ 14.1: Template Parameters [temp.param]
|
// C++ 14.1: Template Parameters [temp.param]
|
||||||
Decl *ParseDeclarationStartingWithTemplate(unsigned Context,
|
Decl *ParseDeclarationStartingWithTemplate(unsigned Context,
|
||||||
SourceLocation &DeclEnd,
|
SourceLocation &DeclEnd,
|
||||||
AccessSpecifier AS = AS_none);
|
AccessSpecifier AS = AS_none,
|
||||||
|
AttributeList *AccessAttrs = 0);
|
||||||
Decl *ParseTemplateDeclarationOrSpecialization(unsigned Context,
|
Decl *ParseTemplateDeclarationOrSpecialization(unsigned Context,
|
||||||
SourceLocation &DeclEnd,
|
SourceLocation &DeclEnd,
|
||||||
AccessSpecifier AS);
|
AccessSpecifier AS,
|
||||||
|
AttributeList *AccessAttrs);
|
||||||
Decl *ParseSingleDeclarationAfterTemplate(
|
Decl *ParseSingleDeclarationAfterTemplate(
|
||||||
unsigned Context,
|
unsigned Context,
|
||||||
const ParsedTemplateInfo &TemplateInfo,
|
const ParsedTemplateInfo &TemplateInfo,
|
||||||
ParsingDeclRAIIObject &DiagsFromParams,
|
ParsingDeclRAIIObject &DiagsFromParams,
|
||||||
SourceLocation &DeclEnd,
|
SourceLocation &DeclEnd,
|
||||||
AccessSpecifier AS=AS_none);
|
AccessSpecifier AS=AS_none,
|
||||||
|
AttributeList *AccessAttrs = 0);
|
||||||
bool ParseTemplateParameters(unsigned Depth,
|
bool ParseTemplateParameters(unsigned Depth,
|
||||||
SmallVectorImpl<Decl*> &TemplateParams,
|
SmallVectorImpl<Decl*> &TemplateParams,
|
||||||
SourceLocation &LAngleLoc,
|
SourceLocation &LAngleLoc,
|
||||||
|
|
|
@ -1838,6 +1838,8 @@ public:
|
||||||
bool NonInheritable = true, bool Inheritable = true);
|
bool NonInheritable = true, bool Inheritable = true);
|
||||||
void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL,
|
void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL,
|
||||||
bool NonInheritable = true, bool Inheritable = true);
|
bool NonInheritable = true, bool Inheritable = true);
|
||||||
|
bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
|
||||||
|
const AttributeList *AttrList);
|
||||||
|
|
||||||
void checkUnusedDeclAttributes(Declarator &D);
|
void checkUnusedDeclAttributes(Declarator &D);
|
||||||
|
|
||||||
|
@ -3414,9 +3416,10 @@ public:
|
||||||
bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
|
bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
|
||||||
const CXXScopeSpec *SS = 0);
|
const CXXScopeSpec *SS = 0);
|
||||||
|
|
||||||
Decl *ActOnAccessSpecifier(AccessSpecifier Access,
|
bool ActOnAccessSpecifier(AccessSpecifier Access,
|
||||||
SourceLocation ASLoc,
|
SourceLocation ASLoc,
|
||||||
SourceLocation ColonLoc);
|
SourceLocation ColonLoc,
|
||||||
|
AttributeList *Attrs = 0);
|
||||||
|
|
||||||
Decl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
|
Decl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
|
||||||
Declarator &D,
|
Declarator &D,
|
||||||
|
|
|
@ -21,7 +21,9 @@ using namespace clang;
|
||||||
/// ParseCXXInlineMethodDef - We parsed and verified that the specified
|
/// ParseCXXInlineMethodDef - We parsed and verified that the specified
|
||||||
/// Declarator is a well formed C++ inline method definition. Now lex its body
|
/// Declarator is a well formed C++ inline method definition. Now lex its body
|
||||||
/// and store its tokens for parsing after the C++ class is complete.
|
/// and store its tokens for parsing after the C++ class is complete.
|
||||||
Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
|
Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
|
||||||
|
AttributeList *AccessAttrs,
|
||||||
|
ParsingDeclarator &D,
|
||||||
const ParsedTemplateInfo &TemplateInfo,
|
const ParsedTemplateInfo &TemplateInfo,
|
||||||
const VirtSpecifiers& VS, ExprResult& Init) {
|
const VirtSpecifiers& VS, ExprResult& Init) {
|
||||||
assert(D.isFunctionDeclarator() && "This isn't a function declarator!");
|
assert(D.isFunctionDeclarator() && "This isn't a function declarator!");
|
||||||
|
@ -43,6 +45,8 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
|
||||||
move(TemplateParams), 0,
|
move(TemplateParams), 0,
|
||||||
VS, /*HasInit=*/false);
|
VS, /*HasInit=*/false);
|
||||||
if (FnD) {
|
if (FnD) {
|
||||||
|
Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs,
|
||||||
|
false, true);
|
||||||
bool TypeSpecContainsAuto
|
bool TypeSpecContainsAuto
|
||||||
= D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
|
= D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
|
||||||
if (Init.get())
|
if (Init.get())
|
||||||
|
|
|
@ -1577,6 +1577,7 @@ bool Parser::isCXX0XFinalKeyword() const {
|
||||||
/// '=' constant-expression
|
/// '=' constant-expression
|
||||||
///
|
///
|
||||||
void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||||
|
AttributeList *AccessAttrs,
|
||||||
const ParsedTemplateInfo &TemplateInfo,
|
const ParsedTemplateInfo &TemplateInfo,
|
||||||
ParsingDeclRAIIObject *TemplateDiags) {
|
ParsingDeclRAIIObject *TemplateDiags) {
|
||||||
if (Tok.is(tok::at)) {
|
if (Tok.is(tok::at)) {
|
||||||
|
@ -1643,7 +1644,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||||
"Nested template improperly parsed?");
|
"Nested template improperly parsed?");
|
||||||
SourceLocation DeclEnd;
|
SourceLocation DeclEnd;
|
||||||
ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd,
|
ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd,
|
||||||
AS);
|
AS, AccessAttrs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1652,7 +1653,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||||
// __extension__ silences extension warnings in the subexpression.
|
// __extension__ silences extension warnings in the subexpression.
|
||||||
ExtensionRAIIObject O(Diags); // Use RAII to do this.
|
ExtensionRAIIObject O(Diags); // Use RAII to do this.
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
return ParseCXXClassMemberDeclaration(AS, TemplateInfo, TemplateDiags);
|
return ParseCXXClassMemberDeclaration(AS, AccessAttrs,
|
||||||
|
TemplateInfo, TemplateDiags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
|
// Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
|
||||||
|
@ -1783,7 +1785,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||||
}
|
}
|
||||||
|
|
||||||
Decl *FunDecl =
|
Decl *FunDecl =
|
||||||
ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo, VS, Init);
|
ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo,
|
||||||
|
VS, Init);
|
||||||
|
|
||||||
for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {
|
for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {
|
||||||
LateParsedAttrs[i]->setDecl(FunDecl);
|
LateParsedAttrs[i]->setDecl(FunDecl);
|
||||||
|
@ -1867,6 +1870,9 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||||
move(TemplateParams),
|
move(TemplateParams),
|
||||||
BitfieldSize.release(),
|
BitfieldSize.release(),
|
||||||
VS, HasDeferredInitializer);
|
VS, HasDeferredInitializer);
|
||||||
|
if (AccessAttrs)
|
||||||
|
Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs,
|
||||||
|
false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the Decl for any late parsed attributes
|
// Set the Decl for any late parsed attributes
|
||||||
|
@ -2109,6 +2115,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
|
||||||
CurAS = AS_private;
|
CurAS = AS_private;
|
||||||
else
|
else
|
||||||
CurAS = AS_public;
|
CurAS = AS_public;
|
||||||
|
ParsedAttributes AccessAttrs(AttrFactory);
|
||||||
|
|
||||||
if (TagDecl) {
|
if (TagDecl) {
|
||||||
// While we still have something to read, read the member-declarations.
|
// While we still have something to read, read the member-declarations.
|
||||||
|
@ -2137,9 +2144,17 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
|
||||||
SourceLocation ASLoc = Tok.getLocation();
|
SourceLocation ASLoc = Tok.getLocation();
|
||||||
unsigned TokLength = Tok.getLength();
|
unsigned TokLength = Tok.getLength();
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
|
AccessAttrs.clear();
|
||||||
|
MaybeParseGNUAttributes(AccessAttrs);
|
||||||
|
|
||||||
SourceLocation EndLoc;
|
SourceLocation EndLoc;
|
||||||
if (Tok.is(tok::colon)) {
|
if (Tok.is(tok::colon)) {
|
||||||
EndLoc = Tok.getLocation();
|
EndLoc = Tok.getLocation();
|
||||||
|
if (Actions.ActOnAccessSpecifier(AS, ASLoc, EndLoc,
|
||||||
|
AccessAttrs.getList())) {
|
||||||
|
// found another attribute than only annotations
|
||||||
|
AccessAttrs.clear();
|
||||||
|
}
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
} else if (Tok.is(tok::semi)) {
|
} else if (Tok.is(tok::semi)) {
|
||||||
EndLoc = Tok.getLocation();
|
EndLoc = Tok.getLocation();
|
||||||
|
@ -2158,7 +2173,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
|
||||||
// FIXME: Make sure we don't have a template here.
|
// FIXME: Make sure we don't have a template here.
|
||||||
|
|
||||||
// Parse all the comma separated declarators.
|
// Parse all the comma separated declarators.
|
||||||
ParseCXXClassMemberDeclaration(CurAS);
|
ParseCXXClassMemberDeclaration(CurAS, AccessAttrs.getList());
|
||||||
}
|
}
|
||||||
|
|
||||||
T.consumeClose();
|
T.consumeClose();
|
||||||
|
@ -2779,7 +2794,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse all the comma separated declarators.
|
// Parse all the comma separated declarators.
|
||||||
ParseCXXClassMemberDeclaration(CurAS);
|
ParseCXXClassMemberDeclaration(CurAS, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Tok.isNot(tok::r_brace)) {
|
if (Tok.isNot(tok::r_brace)) {
|
||||||
|
|
|
@ -26,14 +26,16 @@ using namespace clang;
|
||||||
Decl *
|
Decl *
|
||||||
Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
|
Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
|
||||||
SourceLocation &DeclEnd,
|
SourceLocation &DeclEnd,
|
||||||
AccessSpecifier AS) {
|
AccessSpecifier AS,
|
||||||
|
AttributeList *AccessAttrs) {
|
||||||
ObjCDeclContextSwitch ObjCDC(*this);
|
ObjCDeclContextSwitch ObjCDC(*this);
|
||||||
|
|
||||||
if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) {
|
if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) {
|
||||||
return ParseExplicitInstantiation(SourceLocation(), ConsumeToken(),
|
return ParseExplicitInstantiation(SourceLocation(), ConsumeToken(),
|
||||||
DeclEnd);
|
DeclEnd);
|
||||||
}
|
}
|
||||||
return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS);
|
return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS,
|
||||||
|
AccessAttrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief RAII class that manages the template parameter depth.
|
/// \brief RAII class that manages the template parameter depth.
|
||||||
|
@ -77,7 +79,8 @@ namespace {
|
||||||
Decl *
|
Decl *
|
||||||
Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
|
Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
|
||||||
SourceLocation &DeclEnd,
|
SourceLocation &DeclEnd,
|
||||||
AccessSpecifier AS) {
|
AccessSpecifier AS,
|
||||||
|
AttributeList *AccessAttrs) {
|
||||||
assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
|
assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
|
||||||
"Token does not start a template declaration.");
|
"Token does not start a template declaration.");
|
||||||
|
|
||||||
|
@ -161,7 +164,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
|
||||||
isSpecialization,
|
isSpecialization,
|
||||||
LastParamListWasEmpty),
|
LastParamListWasEmpty),
|
||||||
ParsingTemplateParams,
|
ParsingTemplateParams,
|
||||||
DeclEnd, AS);
|
DeclEnd, AS, AccessAttrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Parse a single declaration that declares a template,
|
/// \brief Parse a single declaration that declares a template,
|
||||||
|
@ -190,13 +193,15 @@ Parser::ParseSingleDeclarationAfterTemplate(
|
||||||
const ParsedTemplateInfo &TemplateInfo,
|
const ParsedTemplateInfo &TemplateInfo,
|
||||||
ParsingDeclRAIIObject &DiagsFromTParams,
|
ParsingDeclRAIIObject &DiagsFromTParams,
|
||||||
SourceLocation &DeclEnd,
|
SourceLocation &DeclEnd,
|
||||||
AccessSpecifier AS) {
|
AccessSpecifier AS,
|
||||||
|
AttributeList *AccessAttrs) {
|
||||||
assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
|
assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
|
||||||
"Template information required");
|
"Template information required");
|
||||||
|
|
||||||
if (Context == Declarator::MemberContext) {
|
if (Context == Declarator::MemberContext) {
|
||||||
// We are parsing a member template.
|
// We are parsing a member template.
|
||||||
ParseCXXClassMemberDeclaration(AS, TemplateInfo, &DiagsFromTParams);
|
ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,
|
||||||
|
&DiagsFromTParams);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3743,6 +3743,22 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Annotation attributes are the only attributes allowed after an access
|
||||||
|
// specifier.
|
||||||
|
bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
|
||||||
|
const AttributeList *AttrList) {
|
||||||
|
for (const AttributeList* l = AttrList; l; l = l->getNext()) {
|
||||||
|
if (l->getKind() == AttributeList::AT_annotate) {
|
||||||
|
handleAnnotateAttr(*this, ASDecl, *l);
|
||||||
|
} else {
|
||||||
|
Diag(l->getLoc(), diag::err_only_annotate_after_access_spec);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// checkUnusedDeclAttributes - Check a list of attributes to see if it
|
/// checkUnusedDeclAttributes - Check a list of attributes to see if it
|
||||||
/// contains any decl attributes that we should warn about.
|
/// contains any decl attributes that we should warn about.
|
||||||
static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) {
|
static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) {
|
||||||
|
|
|
@ -1376,14 +1376,15 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) {
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon.
|
/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon.
|
||||||
Decl *Sema::ActOnAccessSpecifier(AccessSpecifier Access,
|
bool Sema::ActOnAccessSpecifier(AccessSpecifier Access,
|
||||||
SourceLocation ASLoc,
|
SourceLocation ASLoc,
|
||||||
SourceLocation ColonLoc) {
|
SourceLocation ColonLoc,
|
||||||
|
AttributeList *Attrs) {
|
||||||
assert(Access != AS_none && "Invalid kind for syntactic access specifier!");
|
assert(Access != AS_none && "Invalid kind for syntactic access specifier!");
|
||||||
AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext,
|
AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext,
|
||||||
ASLoc, ColonLoc);
|
ASLoc, ColonLoc);
|
||||||
CurContext->addHiddenDecl(ASDecl);
|
CurContext->addHiddenDecl(ASDecl);
|
||||||
return ASDecl;
|
return ProcessAccessDeclAttributeList(ASDecl, Attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CheckOverrideControl - Check C++0x override control semantics.
|
/// CheckOverrideControl - Check C++0x override control semantics.
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
// RUN: c-index-test -test-load-source all %s | FileCheck %s
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
public:
|
||||||
|
__attribute__((annotate("spiffy_method"))) void aMethod();
|
||||||
|
|
||||||
|
public __attribute__((annotate("works"))):
|
||||||
|
void anotherMethod(); // annotation attribute should be propagated.
|
||||||
|
|
||||||
|
private __attribute__((annotate("investigations"))):
|
||||||
|
//propagated annotation should have changed from "works" to "investigations"
|
||||||
|
void inlineMethod() {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// attribute propagation should have stopped here
|
||||||
|
void methodWithoutAttribute();
|
||||||
|
};
|
||||||
|
|
||||||
|
// CHECK: ClassDecl=Test:3:7 (Definition) Extent=[3:1 - 17:2]
|
||||||
|
// CHECK: CXXAccessSpecifier=:4:1 (Definition) Extent=[4:1 - 4:8]
|
||||||
|
// CHECK: CXXMethod=aMethod:5:51 Extent=[5:3 - 5:60]
|
||||||
|
// CHECK: attribute(annotate)=spiffy_method Extent=[5:18 - 5:43]
|
||||||
|
// CHECK: CXXAccessSpecifier=:7:1 (Definition) Extent=[7:1 - 7:43]
|
||||||
|
// CHECK: attribute(annotate)=works Extent=[7:23 - 7:40]
|
||||||
|
// CHECK: CXXMethod=anotherMethod:8:8 Extent=[8:3 - 8:23]
|
||||||
|
// CHECK: attribute(annotate)=works Extent=[7:23 - 7:40]
|
||||||
|
// CHECK: CXXAccessSpecifier=:10:1 (Definition) Extent=[10:1 - 10:53]
|
||||||
|
// CHECK: attribute(annotate)=investigations Extent=[10:24 - 10:50]
|
||||||
|
// CHECK: CXXMethod=inlineMethod:12:8 (Definition) Extent=[12:3 - 12:25]
|
||||||
|
// CHECK: attribute(annotate)=investigations Extent=[10:24 - 10:50]
|
||||||
|
// CHECK: CompoundStmt= Extent=[12:23 - 12:25]
|
||||||
|
// CHECK: CXXAccessSpecifier=:14:1 (Definition) Extent=[14:1 - 14:11]
|
||||||
|
// CHECK: CXXMethod=methodWithoutAttribute:16:8 Extent=[16:3 - 16:32]
|
|
@ -0,0 +1,12 @@
|
||||||
|
// RUN: %clang_cc1 %s -fsyntax-only -verify
|
||||||
|
|
||||||
|
struct X {
|
||||||
|
public __attribute__((unavailable)): // expected-error {{access specifier can only have annotation attributes}}
|
||||||
|
void foo();
|
||||||
|
private __attribute__((annotate("foobar"))):
|
||||||
|
void bar();
|
||||||
|
};
|
||||||
|
|
||||||
|
void f(X x) {
|
||||||
|
x.foo();
|
||||||
|
}
|
|
@ -3200,6 +3200,11 @@ CXString clang_getCursorSpelling(CXCursor C) {
|
||||||
if (clang_isDeclaration(C.kind))
|
if (clang_isDeclaration(C.kind))
|
||||||
return getDeclSpelling(getCursorDecl(C));
|
return getDeclSpelling(getCursorDecl(C));
|
||||||
|
|
||||||
|
if (C.kind == CXCursor_AnnotateAttr) {
|
||||||
|
AnnotateAttr *AA = cast<AnnotateAttr>(cxcursor::getCursorAttr(C));
|
||||||
|
return createCXString(AA->getAnnotation());
|
||||||
|
}
|
||||||
|
|
||||||
return createCXString("");
|
return createCXString("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3521,6 +3526,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
|
||||||
return createCXString("attribute(final)");
|
return createCXString("attribute(final)");
|
||||||
case CXCursor_CXXOverrideAttr:
|
case CXCursor_CXXOverrideAttr:
|
||||||
return createCXString("attribute(override)");
|
return createCXString("attribute(override)");
|
||||||
|
case CXCursor_AnnotateAttr:
|
||||||
|
return createCXString("attribute(annotate)");
|
||||||
case CXCursor_PreprocessingDirective:
|
case CXCursor_PreprocessingDirective:
|
||||||
return createCXString("preprocessing directive");
|
return createCXString("preprocessing directive");
|
||||||
case CXCursor_MacroDefinition:
|
case CXCursor_MacroDefinition:
|
||||||
|
|
|
@ -45,6 +45,7 @@ static CXCursorKind GetCursorKind(const Attr *A) {
|
||||||
case attr::IBOutletCollection: return CXCursor_IBOutletCollectionAttr;
|
case attr::IBOutletCollection: return CXCursor_IBOutletCollectionAttr;
|
||||||
case attr::Final: return CXCursor_CXXFinalAttr;
|
case attr::Final: return CXCursor_CXXFinalAttr;
|
||||||
case attr::Override: return CXCursor_CXXOverrideAttr;
|
case attr::Override: return CXCursor_CXXOverrideAttr;
|
||||||
|
case attr::Annotate: return CXCursor_AnnotateAttr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CXCursor_UnexposedAttr;
|
return CXCursor_UnexposedAttr;
|
||||||
|
|
Loading…
Reference in New Issue