summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-02-19 23:47:15 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-02-19 23:47:15 +0000
commit053214013990ad8ec096dafc64aa7c0ad2b05bc0 (patch)
tree780636c1e0577c4aa63aa31e832b8f8324079cb4 /lib
parent65f991ccbec43b4a860f70594c92528ee8fb7c6f (diff)
downloadclang-053214013990ad8ec096dafc64aa7c0ad2b05bc0.tar.gz
PR15300: Support C++11 attributes on base-specifiers. We don't support any such
attributes yet, so just issue the appropriate diagnostics. Also generalize the fixit for attributes-in-the-wrong-place code and reuse it here, if attributes are placed after the access-specifier or 'virtual' in a base specifier. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175575 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Parse/ParseDecl.cpp19
-rw-r--r--lib/Parse/ParseDeclCXX.cpp50
-rw-r--r--lib/Sema/SemaDeclCXX.cpp17
-rw-r--r--lib/Sema/SemaStmtAttr.cpp4
4 files changed, 63 insertions, 27 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 0dd1e0a6f4..cc47ee1d90 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1144,6 +1144,25 @@ bool Parser::DiagnoseProhibitedCXX11Attribute() {
llvm_unreachable("All cases handled above.");
}
+/// DiagnoseMisplacedCXX11Attribute - We have found the opening square brackets
+/// of a C++11 attribute-specifier in a location where an attribute is not
+/// permitted, but we know where the attributes ought to be written. Parse them
+/// anyway, and provide a fixit moving them to the right place.
+void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
+ SourceLocation CorrectLocation) {
+ assert((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||
+ Tok.is(tok::kw_alignas));
+
+ // Consume the attributes.
+ SourceLocation Loc = Tok.getLocation();
+ ParseCXX11Attributes(Attrs);
+ CharSourceRange AttrRange(SourceRange(Loc, Attrs.Range.getEnd()), true);
+
+ Diag(Loc, diag::err_attributes_not_allowed)
+ << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
+ << FixItHint::CreateRemoval(AttrRange);
+}
+
void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed)
<< attrs.Range;
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 1a1eeb9402..4d428ceea1 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -802,15 +802,18 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
/// class. The result is either a type or null, depending on whether a type
/// name was found.
///
-/// base-type-specifier: [C++ 10.1]
+/// base-type-specifier: [C++11 class.derived]
/// class-or-decltype
-/// class-or-decltype: [C++ 10.1]
+/// class-or-decltype: [C++11 class.derived]
/// nested-name-specifier[opt] class-name
/// decltype-specifier
-/// class-name: [C++ 9.1]
+/// class-name: [C++ class.name]
/// identifier
/// simple-template-id
///
+/// In C++98, instead of base-type-specifier, we have:
+///
+/// ::[opt] nested-name-specifier[opt] class-name
Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
SourceLocation &EndLocation) {
// Ignore attempts to use typename
@@ -1636,26 +1639,33 @@ void Parser::ParseBaseClause(Decl *ClassDecl) {
/// 'public bar' and 'virtual private baz' are each base-specifiers.
///
/// base-specifier: [C++ class.derived]
-/// ::[opt] nested-name-specifier[opt] class-name
-/// 'virtual' access-specifier[opt] ::[opt] nested-name-specifier[opt]
-/// base-type-specifier
-/// access-specifier 'virtual'[opt] ::[opt] nested-name-specifier[opt]
-/// base-type-specifier
+/// attribute-specifier-seq[opt] base-type-specifier
+/// attribute-specifier-seq[opt] 'virtual' access-specifier[opt]
+/// base-type-specifier
+/// attribute-specifier-seq[opt] access-specifier 'virtual'[opt]
+/// base-type-specifier
Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
bool IsVirtual = false;
SourceLocation StartLoc = Tok.getLocation();
+ ParsedAttributesWithRange Attributes(AttrFactory);
+ MaybeParseCXX11Attributes(Attributes);
+
// Parse the 'virtual' keyword.
if (Tok.is(tok::kw_virtual)) {
ConsumeToken();
IsVirtual = true;
}
+ CheckMisplacedCXX11Attribute(Attributes, StartLoc);
+
// Parse an (optional) access specifier.
AccessSpecifier Access = getAccessSpecifierIfPresent();
if (Access != AS_none)
ConsumeToken();
+ CheckMisplacedCXX11Attribute(Attributes, StartLoc);
+
// Parse the 'virtual' keyword (again!), in case it came after the
// access specifier.
if (Tok.is(tok::kw_virtual)) {
@@ -1669,6 +1679,8 @@ Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
IsVirtual = true;
}
+ CheckMisplacedCXX11Attribute(Attributes, StartLoc);
+
// Parse the class-name.
SourceLocation EndLocation;
SourceLocation BaseLoc;
@@ -1688,8 +1700,9 @@ Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
// Notify semantic analysis that we have parsed a complete
// base-specifier.
- return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
- BaseType.get(), BaseLoc, EllipsisLoc);
+ return Actions.ActOnBaseSpecifier(ClassDecl, Range, Attributes, IsVirtual,
+ Access, BaseType.get(), BaseLoc,
+ EllipsisLoc);
}
/// getAccessSpecifierIfPresent - Determine whether the next token is
@@ -2384,7 +2397,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
///
void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
SourceLocation AttrFixitLoc,
- ParsedAttributes &Attrs,
+ ParsedAttributesWithRange &Attrs,
unsigned TagType, Decl *TagDecl) {
assert((TagType == DeclSpec::TST_struct ||
TagType == DeclSpec::TST_interface ||
@@ -2457,20 +2470,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
// These attributes are not allowed to appear here,
// and the only possible place for them to appertain
// to the class would be between class-key and class-name.
- ParsedAttributesWithRange Attributes(AttrFactory);
- MaybeParseCXX11Attributes(Attributes);
- SourceRange AttrRange = Attributes.Range;
- if (AttrRange.isValid()) {
- Diag(AttrRange.getBegin(), diag::err_attributes_not_allowed)
- << AttrRange
- << FixItHint::CreateInsertionFromRange(AttrFixitLoc,
- CharSourceRange(AttrRange, true))
- << FixItHint::CreateRemoval(AttrRange);
-
- // Recover by adding attributes to the attribute list of the class
- // so they can be applied on the class later.
- Attrs.takeAllFrom(Attributes);
- }
+ CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc);
}
if (Tok.is(tok::colon)) {
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 1711c8726e..8b0ccd7146 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1172,6 +1172,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
/// 'public bar' and 'virtual private baz' are each base-specifiers.
BaseResult
Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
+ ParsedAttributes &Attributes,
bool Virtual, AccessSpecifier Access,
ParsedType basetype, SourceLocation BaseLoc,
SourceLocation EllipsisLoc) {
@@ -1183,6 +1184,22 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
if (!Class)
return true;
+ // We do not support any C++11 attributes on base-specifiers yet.
+ // Diagnose any attributes we see.
+ if (!Attributes.empty()) {
+ for (AttributeList *Attr = Attributes.getList(); Attr;
+ Attr = Attr->getNext()) {
+ if (Attr->isInvalid() ||
+ Attr->getKind() == AttributeList::IgnoredAttribute)
+ continue;
+ Diag(Attr->getLoc(),
+ Attr->getKind() == AttributeList::UnknownAttribute
+ ? diag::warn_unknown_attribute_ignored
+ : diag::err_base_specifier_attribute)
+ << Attr->getName();
+ }
+ }
+
TypeSourceInfo *TInfo = 0;
GetTypeFromParser(basetype, &TInfo);
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index b268b4502c..eb0188a0db 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -58,8 +58,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
default:
// if we're here, then we parsed a known attribute, but didn't recognize
// it as a statement attribute => it is declaration attribute
- S.Diag(A.getRange().getBegin(), diag::warn_attribute_invalid_on_stmt)
- << A.getName()->getName() << St->getLocStart();
+ S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt)
+ << A.getName() << St->getLocStart();
return 0;
}
}