forked from OSchip/llvm-project
Process and handle attributes on conditions and for loop variables. Process and
diagnose attributes on alias declarations, using directives, and attribute declarations. llvm-svn: 175649
This commit is contained in:
parent
5cdb345883
commit
54ecd9863f
|
@ -1908,6 +1908,8 @@ def warn_attribute_not_on_decl : Warning<
|
|||
"%0 attribute ignored when parsing type">, InGroup<IgnoredAttributes>;
|
||||
def err_base_specifier_attribute : Error<
|
||||
"%0 attribute cannot be applied to a base specifier">;
|
||||
def err_attribute_declaration : Error<
|
||||
"%0 attribute cannot be used in an attribute declaration">;
|
||||
|
||||
// Availability attribute
|
||||
def warn_availability_unknown_platform : Warning<
|
||||
|
|
|
@ -1800,7 +1800,8 @@ public:
|
|||
Declarator::TheContext Context
|
||||
= Declarator::TypeNameContext,
|
||||
AccessSpecifier AS = AS_none,
|
||||
Decl **OwnedType = 0);
|
||||
Decl **OwnedType = 0,
|
||||
ParsedAttributes *Attrs = 0);
|
||||
|
||||
private:
|
||||
void ParseBlockId(SourceLocation CaretLoc);
|
||||
|
|
|
@ -1447,6 +1447,9 @@ public:
|
|||
SourceLocation AsmLoc,
|
||||
SourceLocation RParenLoc);
|
||||
|
||||
/// \brief Handle a C++11 attribute-declaration.
|
||||
void ActOnAttributeDeclaration(AttributeList *AttrList);
|
||||
|
||||
/// \brief The parser has processed a module import declaration.
|
||||
///
|
||||
/// \param AtLoc The location of the '@' symbol, if any.
|
||||
|
@ -3429,6 +3432,7 @@ public:
|
|||
MultiTemplateParamsArg TemplateParams,
|
||||
SourceLocation UsingLoc,
|
||||
UnqualifiedId &Name,
|
||||
AttributeList *AttrList,
|
||||
TypeResult Type);
|
||||
|
||||
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
|
||||
|
|
|
@ -38,13 +38,16 @@ using namespace clang;
|
|||
TypeResult Parser::ParseTypeName(SourceRange *Range,
|
||||
Declarator::TheContext Context,
|
||||
AccessSpecifier AS,
|
||||
Decl **OwnedType) {
|
||||
Decl **OwnedType,
|
||||
ParsedAttributes *Attrs) {
|
||||
DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context);
|
||||
if (DSC == DSC_normal)
|
||||
DSC = DSC_type_specifier;
|
||||
|
||||
// Parse the common declaration-specifiers piece.
|
||||
DeclSpec DS(AttrFactory);
|
||||
if (Attrs)
|
||||
DS.addAttributes(Attrs->getList());
|
||||
ParseSpecifierQualifierList(DS, AS, DSC);
|
||||
if (OwnedType)
|
||||
*OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : 0;
|
||||
|
|
|
@ -451,24 +451,21 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
|
|||
Decl **OwnedType) {
|
||||
CXXScopeSpec SS;
|
||||
SourceLocation TypenameLoc;
|
||||
bool IsTypeName;
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
bool IsTypeName = false;
|
||||
ParsedAttributesWithRange Attrs(AttrFactory);
|
||||
|
||||
// FIXME: Simply skip the attributes and diagnose, don't bother parsing them.
|
||||
MaybeParseCXX11Attributes(attrs);
|
||||
ProhibitAttributes(attrs);
|
||||
attrs.clear();
|
||||
attrs.Range = SourceRange();
|
||||
MaybeParseCXX11Attributes(Attrs);
|
||||
ProhibitAttributes(Attrs);
|
||||
Attrs.clear();
|
||||
Attrs.Range = SourceRange();
|
||||
|
||||
// Ignore optional 'typename'.
|
||||
// FIXME: This is wrong; we should parse this as a typename-specifier.
|
||||
if (Tok.is(tok::kw_typename)) {
|
||||
TypenameLoc = Tok.getLocation();
|
||||
ConsumeToken();
|
||||
TypenameLoc = ConsumeToken();
|
||||
IsTypeName = true;
|
||||
}
|
||||
else
|
||||
IsTypeName = false;
|
||||
|
||||
// Parse nested-name-specifier.
|
||||
ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
|
||||
|
@ -495,14 +492,13 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
|
|||
return 0;
|
||||
}
|
||||
|
||||
MaybeParseCXX11Attributes(attrs);
|
||||
MaybeParseCXX11Attributes(Attrs);
|
||||
|
||||
// Maybe this is an alias-declaration.
|
||||
bool IsAliasDecl = Tok.is(tok::equal);
|
||||
TypeResult TypeAlias;
|
||||
if (IsAliasDecl) {
|
||||
// TODO: Attribute support. C++0x attributes may appear before the equals.
|
||||
// Where can GNU attributes appear?
|
||||
// TODO: Can GNU attributes appear here?
|
||||
ConsumeToken();
|
||||
|
||||
Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 ?
|
||||
|
@ -547,20 +543,21 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
|
|||
|
||||
TypeAlias = ParseTypeName(0, TemplateInfo.Kind ?
|
||||
Declarator::AliasTemplateContext :
|
||||
Declarator::AliasDeclContext, AS, OwnedType);
|
||||
Declarator::AliasDeclContext, AS, OwnedType,
|
||||
&Attrs);
|
||||
} else {
|
||||
// C++11 attributes are not allowed on a using-declaration, but GNU ones
|
||||
// are.
|
||||
ProhibitAttributes(attrs);
|
||||
ProhibitAttributes(Attrs);
|
||||
|
||||
// Parse (optional) attributes (most likely GNU strong-using extension).
|
||||
MaybeParseGNUAttributes(attrs);
|
||||
MaybeParseGNUAttributes(Attrs);
|
||||
}
|
||||
|
||||
// Eat ';'.
|
||||
DeclEnd = Tok.getLocation();
|
||||
ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
|
||||
!attrs.empty() ? "attributes list" :
|
||||
!Attrs.empty() ? "attributes list" :
|
||||
IsAliasDecl ? "alias declaration" : "using declaration",
|
||||
tok::semi);
|
||||
|
||||
|
@ -592,13 +589,13 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
|
|||
MultiTemplateParamsArg TemplateParamsArg(
|
||||
TemplateParams ? TemplateParams->data() : 0,
|
||||
TemplateParams ? TemplateParams->size() : 0);
|
||||
// FIXME: Propagate attributes.
|
||||
return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,
|
||||
UsingLoc, Name, TypeAlias);
|
||||
UsingLoc, Name, Attrs.getList(),
|
||||
TypeAlias);
|
||||
}
|
||||
|
||||
return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS,
|
||||
Name, attrs.getList(),
|
||||
Name, Attrs.getList(),
|
||||
IsTypeName, TypenameLoc);
|
||||
}
|
||||
|
||||
|
|
|
@ -1383,6 +1383,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut,
|
|||
|
||||
// type-specifier-seq
|
||||
DeclSpec DS(AttrFactory);
|
||||
DS.takeAttributesFrom(attrs);
|
||||
ParseSpecifierQualifierList(DS);
|
||||
|
||||
// declarator
|
||||
|
|
|
@ -1385,9 +1385,6 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
|
|||
if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode?
|
||||
Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
|
||||
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
MaybeParseCXX11Attributes(attrs);
|
||||
|
||||
// In C++0x, "for (T NS:a" might not be a typo for ::
|
||||
bool MightBeForRangeStmt = getLangOpts().CPlusPlus;
|
||||
ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
|
||||
|
|
|
@ -566,7 +566,6 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
|
|||
/// external-declaration: [C99 6.9], declaration: [C++ dcl.dcl]
|
||||
/// function-definition
|
||||
/// declaration
|
||||
/// [C++0x] empty-declaration
|
||||
/// [GNU] asm-definition
|
||||
/// [GNU] __extension__ external-declaration
|
||||
/// [OBJC] objc-class-definition
|
||||
|
@ -578,8 +577,10 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
|
|||
/// [C++] linkage-specification
|
||||
/// [GNU] asm-definition:
|
||||
/// simple-asm-expr ';'
|
||||
/// [C++11] empty-declaration
|
||||
/// [C++11] attribute-declaration
|
||||
///
|
||||
/// [C++0x] empty-declaration:
|
||||
/// [C++11] empty-declaration:
|
||||
/// ';'
|
||||
///
|
||||
/// [C++0x/GNU] 'extern' 'template' declaration
|
||||
|
@ -624,6 +625,13 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
|
|||
HandlePragmaOpenCLExtension();
|
||||
return DeclGroupPtrTy();
|
||||
case tok::semi:
|
||||
// Either a C++11 empty-declaration or attribute-declaration.
|
||||
if (attrs.Range.isValid()) {
|
||||
// FIXME: Add an AST representation for this.
|
||||
Actions.ActOnAttributeDeclaration(attrs.getList());
|
||||
return DeclGroupPtrTy();
|
||||
}
|
||||
|
||||
ConsumeExtraSemi(OutsideFunction);
|
||||
// TODO: Invoke action for top-level semicolon.
|
||||
return DeclGroupPtrTy();
|
||||
|
|
|
@ -6456,7 +6456,9 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
|
|||
Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
|
||||
}
|
||||
|
||||
// FIXME: We ignore attributes for now.
|
||||
if (UDir)
|
||||
ProcessDeclAttributeList(S, UDir, AttrList);
|
||||
|
||||
return UDir;
|
||||
}
|
||||
|
||||
|
@ -7172,6 +7174,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
|
|||
MultiTemplateParamsArg TemplateParamLists,
|
||||
SourceLocation UsingLoc,
|
||||
UnqualifiedId &Name,
|
||||
AttributeList *AttrList,
|
||||
TypeResult Type) {
|
||||
// Skip up to the relevant declaration scope.
|
||||
while (S->getFlags() & Scope::TemplateParamScope)
|
||||
|
@ -7218,6 +7221,8 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
|
|||
if (Invalid)
|
||||
NewTD->setInvalidDecl();
|
||||
|
||||
ProcessDeclAttributeList(S, NewTD, AttrList);
|
||||
|
||||
CheckTypedefForVariablyModifiedType(S, NewTD);
|
||||
Invalid |= NewTD->isInvalidDecl();
|
||||
|
||||
|
@ -10080,6 +10085,25 @@ Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
|
|||
return LinkageSpec;
|
||||
}
|
||||
|
||||
/// \brief Perform semantic checks on a C++11 attribute-declaration.
|
||||
void Sema::ActOnAttributeDeclaration(AttributeList *AttrList) {
|
||||
// FIXME: Build an AST node for an attribute declaration and return it.
|
||||
|
||||
// Since we do not support any attributes which can be used in an attribute
|
||||
// declaration, just diagnose standard and unknown attributes appropriately.
|
||||
for (/**/; AttrList; AttrList = AttrList->getNext()) {
|
||||
if (AttrList->getKind() == AttributeList::IgnoredAttribute ||
|
||||
AttrList->isInvalid())
|
||||
continue;
|
||||
|
||||
Diag(AttrList->getLoc(),
|
||||
AttrList->getKind() == AttributeList::UnknownAttribute
|
||||
? diag::warn_unknown_attribute_ignored
|
||||
: diag::err_attribute_declaration)
|
||||
<< AttrList->getName();
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Perform semantic analysis for the variable declaration that
|
||||
/// occurs within a C++ catch clause, returning the newly-created
|
||||
/// variable.
|
||||
|
|
|
@ -3497,7 +3497,11 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
|
|||
// Make sure there are no unused decl attributes on the declarator.
|
||||
// We don't want to do this for ObjC parameters because we're going
|
||||
// to apply them to the actual parameter declaration.
|
||||
if (D.getContext() != Declarator::ObjCParameterContext)
|
||||
// Likewise, we don't want to do this for alias declarations, because
|
||||
// we are actually going to build a declaration from this eventually.
|
||||
if (D.getContext() != Declarator::ObjCParameterContext &&
|
||||
D.getContext() != Declarator::AliasDeclContext &&
|
||||
D.getContext() != Declarator::AliasTemplateContext)
|
||||
checkUnusedDeclAttributes(D);
|
||||
|
||||
if (getLangOpts().CPlusPlus) {
|
||||
|
|
|
@ -41,6 +41,8 @@ const [[]] int between_attr_2 = 0; // expected-error {{an attribute list cannot
|
|||
int after_attr [[]];
|
||||
int * [[]] ptr_attr;
|
||||
int & [[]] ref_attr = after_attr;
|
||||
int & [[unknown]] ref_attr_2 = after_attr; // expected-warning {{unknown attribute 'unknown' ignored}}
|
||||
int & [[noreturn]] ref_attr_3 = after_attr; // expected-error {{'noreturn' attribute cannot be applied to types}}
|
||||
int && [[]] rref_attr = 0;
|
||||
int array_attr [1] [[]];
|
||||
alignas(8) int aligned_attr;
|
||||
|
@ -112,13 +114,18 @@ extern "C++" [[]] { } // expected-error {{an attribute list cannot appear here}}
|
|||
[[]] asm(""); // expected-error {{an attribute list cannot appear here}}
|
||||
|
||||
[[]] using ns::i; // expected-error {{an attribute list cannot appear here}}
|
||||
[[]] using namespace ns;
|
||||
[[unknown]] using namespace ns; // expected-warning {{unknown attribute 'unknown' ignored}}
|
||||
[[noreturn]] using namespace ns; // expected-error {{'noreturn' attribute only applies to functions and methods}}
|
||||
|
||||
[[]] using T = int; // expected-error {{an attribute list cannot appear here}}
|
||||
using T [[]] = int; // ok
|
||||
template<typename T> using U [[]] = T;
|
||||
using ns::i [[]]; // expected-error {{an attribute list cannot appear here}}
|
||||
using [[]] ns::i; // expected-error {{an attribute list cannot appear here}}
|
||||
using T [[unknown]] = int; // expected-warning {{unknown attribute 'unknown' ignored}}
|
||||
using T [[noreturn]] = int; // expected-error {{'noreturn' attribute only applies to functions and methods}}
|
||||
using V = int; // expected-note {{previous}}
|
||||
using V [[gnu::vector_size(16)]] = int; // expected-error {{redefinition with different types}}
|
||||
|
||||
auto trailing() -> [[]] const int; // expected-error {{an attribute list cannot appear here}}
|
||||
auto trailing() -> const [[]] int; // expected-error {{an attribute list cannot appear here}}
|
||||
|
@ -220,10 +227,10 @@ void bar () {
|
|||
|
||||
// Condition tests
|
||||
void baz () {
|
||||
if ([[]] bool b = true) {
|
||||
switch ([[]] int n { 42 }) {
|
||||
if ([[unknown]] bool b = true) { // expected-warning {{unknown attribute 'unknown' ignored}}
|
||||
switch ([[unknown]] int n { 42 }) { // expected-warning {{unknown attribute 'unknown' ignored}}
|
||||
default:
|
||||
for ([[]] int n = 0; [[]] char b = n < 5; ++b) {
|
||||
for ([[unknown]] int n = 0; [[unknown]] char b = n < 5; ++b) { // expected-warning 2{{unknown attribute 'unknown' ignored}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -240,7 +247,7 @@ void baz () {
|
|||
do {
|
||||
} while ([[]] false); // expected-error {{an attribute list cannot appear here}}
|
||||
|
||||
for ([[]] int n : { 1, 2, 3 }) {
|
||||
for ([[unknown]] int n : { 1, 2, 3 }) { // expected-warning {{unknown attribute 'unknown' ignored}}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,7 +258,7 @@ enum class [[]] EvenMoreSecrets {};
|
|||
|
||||
namespace arguments {
|
||||
void f[[gnu::format(printf, 1, 2)]](const char*, ...);
|
||||
void g() [[unknown::foo(currently arguments of attributes from unknown namespace other than 'gnu' namespace are ignored... blah...)]]; // expected-warning {{unknown attribute 'foo' ignored}}
|
||||
void g() [[unknown::foo(arguments of attributes from unknown namespace other than 'gnu' namespace are ignored... blah...)]]; // expected-warning {{unknown attribute 'foo' ignored}}
|
||||
}
|
||||
|
||||
// Forbid attributes on decl specifiers.
|
||||
|
@ -265,3 +272,6 @@ int [[carries_dependency]] foo(int [[carries_dependency]] x); // expected-error
|
|||
int *[[gnu::unused]] v3; // expected-warning {{attribute 'unused' ignored}}
|
||||
int v4[2][[gnu::unused]]; // expected-warning {{attribute 'unused' ignored}}
|
||||
int v5()[[gnu::unused]]; // expected-warning {{attribute 'unused' ignored}}
|
||||
|
||||
[[attribute_declaration]]; // expected-warning {{unknown attribute 'attribute_declaration' ignored}}
|
||||
[[noreturn]]; // expected-error {{'noreturn' attribute cannot be used in an attribute declaration}}
|
||||
|
|
Loading…
Reference in New Issue