summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp723
1 files changed, 456 insertions, 267 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
index 6a87b78..7b80934 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
@@ -13,6 +13,7 @@
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/OpenCL.h"
@@ -99,18 +100,21 @@ static bool isAttributeLateParsed(const IdentifierInfo &II) {
/// typequal
/// storageclass
///
-/// FIXME: The GCC grammar/code for this construct implies we need two
-/// token lookahead. Comment from gcc: "If they start with an identifier
-/// which is followed by a comma or close parenthesis, then the arguments
-/// start with that identifier; otherwise they are an expression list."
+/// Whether an attribute takes an 'identifier' is determined by the
+/// attrib-name. GCC's behavior here is not worth imitating:
///
-/// GCC does not require the ',' between attribs in an attribute-list.
+/// * In C mode, if the attribute argument list starts with an identifier
+/// followed by a ',' or an ')', and the identifier doesn't resolve to
+/// a type, it is parsed as an identifier. If the attribute actually
+/// wanted an expression, it's out of luck (but it turns out that no
+/// attributes work that way, because C constant expressions are very
+/// limited).
+/// * In C++ mode, if the attribute argument list starts with an identifier,
+/// and the attribute *wants* an identifier, it is parsed as an identifier.
+/// At block scope, any additional tokens between the identifier and the
+/// ',' or ')' are ignored, otherwise they produce a parse error.
///
-/// At the moment, I am not doing 2 token lookahead. I am also unaware of
-/// any attributes that don't work (based on my limited testing). Most
-/// attributes are very simple in practice. Until we find a bug, I don't see
-/// a pressing need to implement the 2 token lookahead.
-
+/// We follow the C++ model, but don't allow junk after the identifier.
void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
SourceLocation *endLoc,
LateParsedAttrList *LateAttrs) {
@@ -120,11 +124,11 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
ConsumeToken();
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
"attribute")) {
- SkipUntil(tok::r_paren, true); // skip until ) or ;
+ SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ;
return;
}
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) {
- SkipUntil(tok::r_paren, true); // skip until ) or ;
+ SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ;
return;
}
// Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") ))
@@ -163,28 +167,76 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
0, SourceLocation(), AttributeList::AS_GNU);
}
} else {
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc,
- 0, SourceLocation(), 0, 0, AttributeList::AS_GNU);
+ attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ AttributeList::AS_GNU);
}
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
- SkipUntil(tok::r_paren, false);
+ SkipUntil(tok::r_paren, StopAtSemi);
SourceLocation Loc = Tok.getLocation();
- if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
- SkipUntil(tok::r_paren, false);
- }
+ if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+ SkipUntil(tok::r_paren, StopAtSemi);
if (endLoc)
*endLoc = Loc;
}
}
-/// \brief Determine whether the given attribute has all expression arguments.
-static bool attributeHasExprArgs(const IdentifierInfo &II) {
- return llvm::StringSwitch<bool>(II.getName())
-#include "clang/Parse/AttrExprArgs.inc"
+/// \brief Normalizes an attribute name by dropping prefixed and suffixed __.
+static StringRef normalizeAttrName(StringRef Name) {
+ if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
+ Name = Name.drop_front(2).drop_back(2);
+ return Name;
+}
+
+/// \brief Determine whether the given attribute has an identifier argument.
+static bool attributeHasIdentifierArg(const IdentifierInfo &II) {
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
+#include "clang/Parse/AttrIdentifierArg.inc"
+ .Default(false);
+}
+
+/// \brief Determine whether the given attribute parses a type argument.
+static bool attributeIsTypeArgAttr(const IdentifierInfo &II) {
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
+#include "clang/Parse/AttrTypeArg.inc"
.Default(false);
}
+IdentifierLoc *Parser::ParseIdentifierLoc() {
+ assert(Tok.is(tok::identifier) && "expected an identifier");
+ IdentifierLoc *IL = IdentifierLoc::create(Actions.Context,
+ Tok.getLocation(),
+ Tok.getIdentifierInfo());
+ ConsumeToken();
+ return IL;
+}
+
+void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs,
+ SourceLocation *EndLoc) {
+ BalancedDelimiterTracker Parens(*this, tok::l_paren);
+ Parens.consumeOpen();
+
+ TypeResult T;
+ if (Tok.isNot(tok::r_paren))
+ T = ParseTypeName();
+
+ if (Parens.consumeClose())
+ return;
+
+ if (T.isInvalid())
+ return;
+
+ if (T.isUsable())
+ Attrs.addNewTypeAttr(&AttrName,
+ SourceRange(AttrNameLoc, Parens.getCloseLocation()), 0,
+ AttrNameLoc, T.get(), AttributeList::AS_GNU);
+ else
+ Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()),
+ 0, AttrNameLoc, 0, 0, AttributeList::AS_GNU);
+}
+
/// Parse the arguments to a parameterized GNU attribute or
/// a C++11 attribute in "gnu" namespace.
void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
@@ -197,89 +249,65 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
+ AttributeList::Kind AttrKind =
+ AttributeList::getKind(AttrName, ScopeName, Syntax);
+
// Availability attributes have their own grammar.
- if (AttrName->isStr("availability")) {
+ // FIXME: All these cases fail to pass in the syntax and scope, and might be
+ // written as C++11 gnu:: attributes.
+ if (AttrKind == AttributeList::AT_Availability) {
ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc);
return;
}
- // Thread safety attributes fit into the FIXME case above, so we
- // just parse the arguments as a list of expressions
+ // Thread safety attributes are parsed in an unevaluated context.
+ // FIXME: Share the bulk of the parsing code here and just pull out
+ // the unevaluated context.
if (IsThreadSafetyAttribute(AttrName->getName())) {
ParseThreadSafetyAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc);
return;
}
// Type safety attributes have their own grammar.
- if (AttrName->isStr("type_tag_for_datatype")) {
+ if (AttrKind == AttributeList::AT_TypeTagForDatatype) {
ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc);
return;
}
+ // Some attributes expect solely a type parameter.
+ if (attributeIsTypeArgAttr(*AttrName)) {
+ ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, EndLoc);
+ return;
+ }
- ConsumeParen(); // ignore the left paren loc for now
-
- IdentifierInfo *ParmName = 0;
- SourceLocation ParmLoc;
- bool BuiltinType = false;
+ // Ignore the left paren location for now.
+ ConsumeParen();
- TypeResult T;
- SourceRange TypeRange;
- bool TypeParsed = false;
+ ArgsVector ArgExprs;
- switch (Tok.getKind()) {
- case tok::kw_char:
- case tok::kw_wchar_t:
- case tok::kw_char16_t:
- case tok::kw_char32_t:
- case tok::kw_bool:
- case tok::kw_short:
- case tok::kw_int:
- case tok::kw_long:
- case tok::kw___int64:
- case tok::kw___int128:
- case tok::kw_signed:
- case tok::kw_unsigned:
- case tok::kw_float:
- case tok::kw_double:
- case tok::kw_void:
- case tok::kw_typeof:
- // __attribute__(( vec_type_hint(char) ))
- BuiltinType = true;
- T = ParseTypeName(&TypeRange);
- TypeParsed = true;
- break;
-
- case tok::identifier:
- if (AttrName->isStr("vec_type_hint")) {
- T = ParseTypeName(&TypeRange);
- TypeParsed = true;
- break;
+ if (Tok.is(tok::identifier)) {
+ // If this attribute wants an 'identifier' argument, make it so.
+ bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName);
+
+ // If we don't know how to parse this attribute, but this is the only
+ // token in this argument, assume it's meant to be an identifier.
+ if (AttrKind == AttributeList::UnknownAttribute ||
+ AttrKind == AttributeList::IgnoredAttribute) {
+ const Token &Next = NextToken();
+ IsIdentifierArg = Next.is(tok::r_paren) || Next.is(tok::comma);
}
- // If the attribute has all expression arguments, and not a "parameter",
- // break out to handle it below.
- if (attributeHasExprArgs(*AttrName))
- break;
- ParmName = Tok.getIdentifierInfo();
- ParmLoc = ConsumeToken();
- break;
- default:
- break;
+ if (IsIdentifierArg)
+ ArgExprs.push_back(ParseIdentifierLoc());
}
- ExprVector ArgExprs;
- bool isInvalid = false;
- bool isParmType = false;
-
- if (!BuiltinType && !AttrName->isStr("vec_type_hint") &&
- (ParmLoc.isValid() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren))) {
+ if (!ArgExprs.empty() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren)) {
// Eat the comma.
- if (ParmLoc.isValid())
+ if (!ArgExprs.empty())
ConsumeToken();
// Parse the non-empty comma-separated list of expressions.
while (1) {
ExprResult ArgExpr(ParseAssignmentExpression());
if (ArgExpr.isInvalid()) {
- SkipUntil(tok::r_paren);
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
}
ArgExprs.push_back(ArgExpr.release());
@@ -288,48 +316,12 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
ConsumeToken(); // Eat the comma, move to the next argument
}
}
- else if (Tok.is(tok::less) && AttrName->isStr("iboutletcollection")) {
- if (!ExpectAndConsume(tok::less, diag::err_expected_less_after, "<",
- tok::greater)) {
- while (Tok.is(tok::identifier)) {
- ConsumeToken();
- if (Tok.is(tok::greater))
- break;
- if (Tok.is(tok::comma)) {
- ConsumeToken();
- continue;
- }
- }
- if (Tok.isNot(tok::greater))
- Diag(Tok, diag::err_iboutletcollection_with_protocol);
- SkipUntil(tok::r_paren, false, true); // skip until ')'
- }
- } else if (AttrName->isStr("vec_type_hint")) {
- if (T.get() && !T.isInvalid())
- isParmType = true;
- else {
- if (Tok.is(tok::identifier))
- ConsumeToken();
- if (TypeParsed)
- isInvalid = true;
- }
- }
SourceLocation RParen = Tok.getLocation();
- if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen) &&
- !isInvalid) {
+ if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc;
- if (isParmType) {
- Attrs.addNewTypeAttr(AttrName, SourceRange(AttrLoc, RParen), ScopeName,
- ScopeLoc, ParmName, ParmLoc, T.get(), Syntax);
- } else {
- AttributeList *attr = Attrs.addNew(
- AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc, ParmName,
- ParmLoc, ArgExprs.data(), ArgExprs.size(), Syntax);
- if (BuiltinType &&
- attr->getKind() == AttributeList::AT_IBOutletCollection)
- Diag(Tok, diag::err_iboutletcollection_builtintype);
- }
+ Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc,
+ ArgExprs.data(), ArgExprs.size(), Syntax);
}
}
@@ -349,9 +341,9 @@ void Parser::ParseMicrosoftDeclSpecWithSingleArg(IdentifierInfo *AttrName,
T.skipToEnd();
return;
}
- Expr *ExprList = ArgExpr.take();
- Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(),
- &ExprList, 1, AttributeList::AS_Declspec);
+ ArgsUnion ExprList = ArgExpr.take();
+ Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, &ExprList, 1,
+ AttributeList::AS_Declspec);
T.consumeClose();
}
@@ -399,8 +391,7 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident,
if (Tok.getKind() == tok::l_paren)
ParseMicrosoftDeclSpecWithSingleArg(Ident, Loc, Attrs);
else
- Attrs.addNew(Ident, Loc, 0, Loc, 0, SourceLocation(), 0, 0,
- AttributeList::AS_Declspec);
+ Attrs.addNew(Ident, Loc, 0, Loc, 0, 0, AttributeList::AS_Declspec);
} else if (Ident->getName() == "property") {
// The property declspec is more complex in that it can take one or two
// assignment expressions as a parameter, but the lhs of the assignment
@@ -513,8 +504,7 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident,
// Only add the property attribute if it was well-formed.
if (!HasInvalidAccessor) {
- Attrs.addNewPropertyAttr(Ident, Loc, 0, SourceLocation(), 0,
- SourceLocation(),
+ Attrs.addNewPropertyAttr(Ident, Loc, 0, SourceLocation(),
AccessorNames[AK_Get], AccessorNames[AK_Put],
AttributeList::AS_Declspec);
}
@@ -588,8 +578,8 @@ void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &Attrs) {
//
// Alternatively, if the identifier is a simple one, then it requires no
// arguments and can be turned into an attribute directly.
- Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(),
- 0, 0, AttributeList::AS_Declspec);
+ Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ AttributeList::AS_Declspec);
else
ParseComplexMicrosoftDeclSpec(AttrName, AttrNameLoc, Attrs);
}
@@ -601,11 +591,12 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) ||
Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___cdecl) ||
Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64) ||
- Tok.is(tok::kw___ptr32) || Tok.is(tok::kw___unaligned)) {
+ Tok.is(tok::kw___ptr32) || Tok.is(tok::kw___unaligned) ||
+ Tok.is(tok::kw___sptr) || Tok.is(tok::kw___uptr)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0, AttributeList::AS_Keyword);
+ attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ AttributeList::AS_Keyword);
}
}
@@ -614,8 +605,8 @@ void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) {
while (Tok.is(tok::kw___pascal)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0, AttributeList::AS_Keyword);
+ attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ AttributeList::AS_Keyword);
}
}
@@ -624,8 +615,8 @@ void Parser::ParseOpenCLAttributes(ParsedAttributes &attrs) {
while (Tok.is(tok::kw___kernel)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0, AttributeList::AS_Keyword);
+ attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ AttributeList::AS_Keyword);
}
}
@@ -692,7 +683,8 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
if (!Tok.is(tok::numeric_constant)) {
Diag(Tok, diag::err_expected_version);
- SkipUntil(tok::comma, tok::r_paren, true, true, true);
+ SkipUntil(tok::comma, tok::r_paren,
+ StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
return VersionTuple();
}
@@ -720,7 +712,8 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
if (AfterMajor == 0) {
Diag(Tok, diag::err_expected_version);
- SkipUntil(tok::comma, tok::r_paren, true, true, true);
+ SkipUntil(tok::comma, tok::r_paren,
+ StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
return VersionTuple();
}
@@ -738,7 +731,8 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
if (ThisTokBegin[AfterMajor] != '.' || (AfterMajor + 1 == ActualLength)) {
Diag(Tok, diag::err_expected_version);
- SkipUntil(tok::comma, tok::r_paren, true, true, true);
+ SkipUntil(tok::comma, tok::r_paren,
+ StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
return VersionTuple();
}
@@ -765,7 +759,8 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
// If what follows is not a '.', we have a problem.
if (ThisTokBegin[AfterMinor] != '.') {
Diag(Tok, diag::err_expected_version);
- SkipUntil(tok::comma, tok::r_paren, true, true, true);
+ SkipUntil(tok::comma, tok::r_paren,
+ StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
return VersionTuple();
}
@@ -779,7 +774,8 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
if (AfterSubminor != ActualLength) {
Diag(Tok, diag::err_expected_version);
- SkipUntil(tok::comma, tok::r_paren, true, true, true);
+ SkipUntil(tok::comma, tok::r_paren,
+ StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
return VersionTuple();
}
ConsumeToken();
@@ -809,9 +805,6 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
SourceLocation AvailabilityLoc,
ParsedAttributes &attrs,
SourceLocation *endLoc) {
- SourceLocation PlatformLoc;
- IdentifierInfo *Platform = 0;
-
enum { Introduced, Deprecated, Obsoleted, Unknown };
AvailabilityChange Changes[Unknown];
ExprResult MessageExpr;
@@ -826,11 +819,10 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
// Parse the platform name,
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_availability_expected_platform);
- SkipUntil(tok::r_paren);
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
}
- Platform = Tok.getIdentifierInfo();
- PlatformLoc = ConsumeToken();
+ IdentifierLoc *Platform = ParseIdentifierLoc();
// Parse the ',' following the platform name.
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::r_paren))
@@ -851,7 +843,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
do {
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_availability_expected_change);
- SkipUntil(tok::r_paren);
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
}
IdentifierInfo *Keyword = Tok.getIdentifierInfo();
@@ -874,15 +866,15 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
if (Tok.isNot(tok::equal)) {
Diag(Tok, diag::err_expected_equal_after)
<< Keyword;
- SkipUntil(tok::r_paren);
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
}
ConsumeToken();
if (Keyword == Ident_message) {
- if (!isTokenStringLiteral()) {
+ if (Tok.isNot(tok::string_literal)) { // Also reject wide string literals.
Diag(Tok, diag::err_expected_string_literal)
<< /*Source='availability attribute'*/2;
- SkipUntil(tok::r_paren);
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
}
MessageExpr = ParseStringLiteralExpression();
@@ -893,7 +885,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
VersionTuple Version = ParseVersionTuple(VersionRange);
if (Version.empty()) {
- SkipUntil(tok::r_paren);
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
}
@@ -959,7 +951,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
attrs.addNew(&Availability,
SourceRange(AvailabilityLoc, T.getCloseLocation()),
0, AvailabilityLoc,
- Platform, PlatformLoc,
+ Platform,
Changes[Introduced],
Changes[Deprecated],
Changes[Obsoleted],
@@ -1062,9 +1054,8 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
// Allow 'this' within late-parsed attributes.
- Sema::CXXThisScopeRAII ThisScope(Actions, RD,
- /*TypeQuals=*/0,
- ND && RD && ND->isCXXInstanceMember());
+ Sema::CXXThisScopeRAII ThisScope(Actions, RD, /*TypeQuals=*/0,
+ ND && ND->isCXXInstanceMember());
if (LA.Decls.size() == 1) {
// If the Decl is templatized, add template parameters to scope.
@@ -1161,7 +1152,7 @@ void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName,
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
- ExprVector ArgExprs;
+ ArgsVector ArgExprs;
bool ArgExprsOk = true;
// now parse the list of expressions
@@ -1181,8 +1172,8 @@ void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName,
}
// Match the ')'.
if (ArgExprsOk && !T.consumeClose()) {
- Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(),
- ArgExprs.data(), ArgExprs.size(), AttributeList::AS_GNU);
+ Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc, ArgExprs.data(),
+ ArgExprs.size(), AttributeList::AS_GNU);
}
if (EndLoc)
*EndLoc = T.getCloseLocation();
@@ -1202,8 +1193,7 @@ void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
T.skipToEnd();
return;
}
- IdentifierInfo *ArgumentKind = Tok.getIdentifierInfo();
- SourceLocation ArgumentKindLoc = ConsumeToken();
+ IdentifierLoc *ArgumentKind = ParseIdentifierLoc();
if (Tok.isNot(tok::comma)) {
Diag(Tok, diag::err_expected_comma);
@@ -1243,9 +1233,9 @@ void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
if (!T.consumeClose()) {
Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, 0, AttrNameLoc,
- ArgumentKind, ArgumentKindLoc,
- MatchingCType.release(), LayoutCompatible,
- MustBeNull, AttributeList::AS_GNU);
+ ArgumentKind, MatchingCType.release(),
+ LayoutCompatible, MustBeNull,
+ AttributeList::AS_GNU);
}
if (EndLoc)
@@ -1276,7 +1266,7 @@ bool Parser::DiagnoseProhibitedCXX11Attribute() {
// Parse and discard the attributes.
SourceLocation BeginLoc = ConsumeBracket();
ConsumeBracket();
- SkipUntil(tok::r_square, /*StopAtSemi*/ false);
+ SkipUntil(tok::r_square);
assert(Tok.is(tok::r_square) && "isCXX11AttributeSpecifier lied");
SourceLocation EndLoc = ConsumeBracket();
Diag(BeginLoc, diag::err_attributes_not_allowed)
@@ -1412,8 +1402,14 @@ Parser::ParseSimpleDeclaration(StmtVector &Stmts, unsigned Context,
// Parse the common declaration-specifiers piece.
ParsingDeclSpec DS(*this);
- ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
- getDeclSpecContextFromDeclaratorContext(Context));
+ DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext(Context);
+ ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, DSContext);
+
+ // If we had a free-standing type definition with a missing semicolon, we
+ // may get this far before the problem becomes obvious.
+ if (DS.hasTagDefinition() &&
+ DiagnoseMissingSemiAfterTagDefinition(DS, AS_none, DSContext))
+ return DeclGroupPtrTy();
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
// declaration-specifiers init-declarator-list[opt] ';'
@@ -1507,7 +1503,7 @@ void Parser::SkipMalformedDecl() {
// Skip until matching }, then stop. We've probably skipped over
// a malformed class or function definition or similar.
ConsumeBrace();
- SkipUntil(tok::r_brace, /*StopAtSemi*/false);
+ SkipUntil(tok::r_brace);
if (Tok.is(tok::comma) || Tok.is(tok::l_brace) || Tok.is(tok::kw_try)) {
// This declaration isn't over yet. Keep skipping.
continue;
@@ -1518,12 +1514,12 @@ void Parser::SkipMalformedDecl() {
case tok::l_square:
ConsumeBracket();
- SkipUntil(tok::r_square, /*StopAtSemi*/false);
+ SkipUntil(tok::r_square);
continue;
case tok::l_paren:
ConsumeParen();
- SkipUntil(tok::r_paren, /*StopAtSemi*/false);
+ SkipUntil(tok::r_paren);
continue;
case tok::r_brace:
@@ -1636,7 +1632,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
} else {
if (Tok.is(tok::l_brace)) {
Diag(Tok, diag::err_function_definition_not_allowed);
- SkipUntil(tok::r_brace, true, true);
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
}
}
}
@@ -1666,7 +1662,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
Actions.ActOnCXXForRangeDecl(ThisDecl);
Actions.FinalizeDeclaration(ThisDecl);
D.complete(ThisDecl);
- return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, &ThisDecl, 1);
+ return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, ThisDecl);
}
SmallVector<Decl *, 8> DeclsInGroup;
@@ -1727,15 +1723,13 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
// declaration specifier, just assume it was missing and continue parsing.
// Otherwise things are very confused and we skip to recover.
if (!isDeclarationSpecifier()) {
- SkipUntil(tok::r_brace, true, true);
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
if (Tok.is(tok::semi))
ConsumeToken();
}
}
- return Actions.FinalizeDeclaratorGroup(getCurScope(), DS,
- DeclsInGroup.data(),
- DeclsInGroup.size());
+ return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
}
/// Parse an optional simple-asm-expr and attributes, and attach them to a
@@ -1746,7 +1740,7 @@ bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) {
SourceLocation Loc;
ExprResult AsmLabel(ParseSimpleAsm(&Loc));
if (AsmLabel.isInvalid()) {
- SkipUntil(tok::semi, true, true);
+ SkipUntil(tok::semi, StopBeforeMatch);
return true;
}
@@ -1798,24 +1792,53 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
break;
case ParsedTemplateInfo::Template:
- case ParsedTemplateInfo::ExplicitSpecialization:
+ case ParsedTemplateInfo::ExplicitSpecialization: {
ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
*TemplateInfo.TemplateParams,
D);
+ if (VarTemplateDecl *VT = dyn_cast_or_null<VarTemplateDecl>(ThisDecl))
+ // Re-direct this decl to refer to the templated decl so that we can
+ // initialize it.
+ ThisDecl = VT->getTemplatedDecl();
break;
-
+ }
case ParsedTemplateInfo::ExplicitInstantiation: {
- DeclResult ThisRes
- = Actions.ActOnExplicitInstantiation(getCurScope(),
- TemplateInfo.ExternLoc,
- TemplateInfo.TemplateLoc,
- D);
- if (ThisRes.isInvalid()) {
- SkipUntil(tok::semi, true, true);
- return 0;
+ if (Tok.is(tok::semi)) {
+ DeclResult ThisRes = Actions.ActOnExplicitInstantiation(
+ getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, D);
+ if (ThisRes.isInvalid()) {
+ SkipUntil(tok::semi, StopBeforeMatch);
+ return 0;
+ }
+ ThisDecl = ThisRes.get();
+ } else {
+ // FIXME: This check should be for a variable template instantiation only.
+
+ // Check that this is a valid instantiation
+ if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ // If the declarator-id is not a template-id, issue a diagnostic and
+ // recover by ignoring the 'template' keyword.
+ Diag(Tok, diag::err_template_defn_explicit_instantiation)
+ << 2 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);
+ ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
+ } else {
+ SourceLocation LAngleLoc =
+ PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
+ Diag(D.getIdentifierLoc(),
+ diag::err_explicit_instantiation_with_definition)
+ << SourceRange(TemplateInfo.TemplateLoc)
+ << FixItHint::CreateInsertion(LAngleLoc, "<>");
+
+ // Recover as if it were an explicit specialization.
+ TemplateParameterLists FakedParamLists;
+ FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
+ 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0,
+ LAngleLoc));
+
+ ThisDecl =
+ Actions.ActOnTemplateDeclarator(getCurScope(), FakedParamLists, D);
+ }
}
-
- ThisDecl = ThisRes.get();
break;
}
}
@@ -1826,6 +1849,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
// If a '==' or '+=' is found, suggest a fixit to '='.
if (isTokenEqualOrEqualTypo()) {
ConsumeToken();
+
if (Tok.is(tok::kw_delete)) {
if (D.isFunctionDeclarator())
Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
@@ -1859,7 +1883,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
}
if (Init.isInvalid()) {
- SkipUntil(tok::comma, true, true);
+ SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
Actions.ActOnInitializerError(ThisDecl);
} else
Actions.AddInitializerToDecl(ThisDecl, Init.take(),
@@ -1880,7 +1904,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
if (ParseExpressionList(Exprs, CommaLocs)) {
Actions.ActOnInitializerError(ThisDecl);
- SkipUntil(tok::r_paren);
+ SkipUntil(tok::r_paren, StopAtSemi);
if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
@@ -2063,6 +2087,8 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
DS.getStorageClassSpec() == DeclSpec::SCS_auto) {
// Don't require a type specifier if we have the 'auto' storage class
// specifier in C++98 -- we'll promote it to a type specifier.
+ if (SS)
+ AnnotateScopeToken(*SS, /*IsNewAnnotation*/false);
return false;
}
@@ -2124,16 +2150,6 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// Look ahead to the next token to try to figure out what this declaration
// was supposed to be.
switch (NextToken().getKind()) {
- case tok::comma:
- case tok::equal:
- case tok::kw_asm:
- case tok::l_brace:
- case tok::l_square:
- case tok::semi:
- // This looks like a variable declaration. The type is probably missing.
- // We're done parsing decl-specifiers.
- return false;
-
case tok::l_paren: {
// static x(4); // 'x' is not a type
// x(int n); // 'x' is not a type
@@ -2146,12 +2162,37 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
ConsumeToken();
TPResult TPR = TryParseDeclarator(/*mayBeAbstract*/false);
PA.Revert();
- if (TPR == TPResult::False())
- return false;
- // The identifier is followed by a parenthesized declarator.
- // It's supposed to be a type.
- break;
+
+ if (TPR != TPResult::False()) {
+ // The identifier is followed by a parenthesized declarator.
+ // It's supposed to be a type.
+ break;
+ }
+
+ // If we're in a context where we could be declaring a constructor,
+ // check whether this is a constructor declaration with a bogus name.
+ if (DSC == DSC_class || (DSC == DSC_top_level && SS)) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (Actions.isCurrentClassNameTypo(II, SS)) {
+ Diag(Loc, diag::err_constructor_bad_name)
+ << Tok.getIdentifierInfo() << II
+ << FixItHint::CreateReplacement(Tok.getLocation(), II->getName());
+ Tok.setIdentifierInfo(II);
+ }
+ }
+ // Fall through.
}
+ case tok::comma:
+ case tok::equal:
+ case tok::kw_asm:
+ case tok::l_brace:
+ case tok::l_square:
+ case tok::semi:
+ // This looks like a variable or function declaration. The type is
+ // probably missing. We're done parsing decl-specifiers.
+ if (SS)
+ AnnotateScopeToken(*SS, /*IsNewAnnotation*/false);
+ return false;
default:
// This is probably supposed to be a type. This includes cases like:
@@ -2270,7 +2311,7 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
SourceLocation EllipsisLoc;
ExprResult ArgExpr = ParseAlignArgument(T.getOpenLocation(), EllipsisLoc);
if (ArgExpr.isInvalid()) {
- SkipUntil(tok::r_paren);
+ T.skipToEnd();
return;
}
@@ -2278,10 +2319,105 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
if (EndLoc)
*EndLoc = T.getCloseLocation();
- ExprVector ArgExprs;
+ ArgsVector ArgExprs;
ArgExprs.push_back(ArgExpr.release());
- Attrs.addNew(KWName, KWLoc, 0, KWLoc, 0, T.getOpenLocation(),
- ArgExprs.data(), 1, AttributeList::AS_Keyword, EllipsisLoc);
+ Attrs.addNew(KWName, KWLoc, 0, KWLoc, ArgExprs.data(), 1,
+ AttributeList::AS_Keyword, EllipsisLoc);
+}
+
+/// Determine whether we're looking at something that might be a declarator
+/// in a simple-declaration. If it can't possibly be a declarator, maybe
+/// diagnose a missing semicolon after a prior tag definition in the decl
+/// specifier.
+///
+/// \return \c true if an error occurred and this can't be any kind of
+/// declaration.
+bool
+Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
+ DeclSpecContext DSContext,
+ LateParsedAttrList *LateAttrs) {
+ assert(DS.hasTagDefinition() && "shouldn't call this");
+
+ bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
+ bool HasMissingSemi = false;
+
+ if (getLangOpts().CPlusPlus &&
+ (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
+ Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id)) &&
+ TryAnnotateCXXScopeToken(EnteringContext)) {
+ SkipMalformedDecl();
+ return true;
+ }
+
+ // Determine whether the following tokens could possibly be a
+ // declarator.
+ if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
+ const Token &Next = NextToken();
+ // These tokens cannot come after the declarator-id in a
+ // simple-declaration, and are likely to come after a type-specifier.
+ HasMissingSemi = Next.is(tok::star) || Next.is(tok::amp) ||
+ Next.is(tok::ampamp) || Next.is(tok::identifier) ||
+ Next.is(tok::annot_cxxscope) ||
+ Next.is(tok::coloncolon);
+ } else if (Tok.is(tok::annot_cxxscope) &&
+ NextToken().is(tok::identifier) &&
+ DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
+ // We almost certainly have a missing semicolon. Look up the name and
+ // check; if it names a type, we're missing a semicolon.
+ CXXScopeSpec SS;
+ Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
+ Tok.getAnnotationRange(), SS);
+ const Token &Next = NextToken();
+ IdentifierInfo *Name = Next.getIdentifierInfo();
+ Sema::NameClassification Classification =
+ Actions.ClassifyName(getCurScope(), SS, Name, Next.getLocation(),
+ NextToken(), /*IsAddressOfOperand*/false);
+ switch (Classification.getKind()) {
+ case Sema::NC_Error:
+ SkipMalformedDecl();
+ return true;
+
+ case Sema::NC_Keyword:
+ case Sema::NC_NestedNameSpecifier:
+ llvm_unreachable("typo correction and nested name specifiers not "
+ "possible here");
+
+ case Sema::NC_Type:
+ case Sema::NC_TypeTemplate:
+ // Not a previously-declared non-type entity.
+ HasMissingSemi = true;
+ break;
+
+ case Sema::NC_Unknown:
+ case Sema::NC_Expression:
+ case Sema::NC_VarTemplate:
+ case Sema::NC_FunctionTemplate:
+ // Might be a redeclaration of a prior entity.
+ HasMissingSemi = false;
+ break;
+ }
+ } else if (Tok.is(tok::kw_typename) || Tok.is(tok::annot_typename)) {
+ HasMissingSemi = true;
+ }
+
+ if (!HasMissingSemi)
+ return false;
+
+ Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getLocEnd()),
+ diag::err_expected_semi_after_tagdecl)
+ << DeclSpec::getSpecifierName(DS.getTypeSpecType());
+
+ // Try to recover from the typo, by dropping the tag definition and parsing
+ // the problematic tokens as a type.
+ //
+ // FIXME: Split the DeclSpec into pieces for the standalone
+ // declaration and pieces for the following declaration, instead
+ // of assuming that all the other pieces attach to new declaration,
+ // and call ParsedFreeStandingDeclSpec as appropriate.
+ DS.ClearTypeSpecType();
+ ParsedTemplateInfo NotATemplate;
+ ParseDeclarationSpecifiers(DS, NotATemplate, AS, DSContext, LateAttrs);
+ return false;
}
/// ParseDeclarationSpecifiers
@@ -2402,7 +2538,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::coloncolon: // ::foo::bar
// C++ scope specifier. Annotate and loop, or bail out on error.
- if (TryAnnotateCXXScopeToken(true)) {
+ if (TryAnnotateCXXScopeToken(EnteringContext)) {
if (!DS.hasTypeSpecifier())
DS.SetTypeSpecError();
goto DoneWithDeclSpec;
@@ -2524,7 +2660,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// erroneous: We already checked about that it has no type specifier, and
// C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the
// typename.
- if (TypeRep == 0) {
+ if (!TypeRep) {
ConsumeToken(); // Eat the scope spec so the identifier is current.
ParsedAttributesWithRange Attrs(AttrFactory);
if (ParseImplicitInt(DS, &SS, TemplateInfo, AS, DSContext, Attrs)) {
@@ -2552,6 +2688,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
}
case tok::annot_typename: {
+ // If we've previously seen a tag definition, we were almost surely
+ // missing a semicolon after it.
+ if (DS.hasTypeSpecifier() && DS.hasTagDefinition())
+ goto DoneWithDeclSpec;
+
if (Tok.getAnnotationValue()) {
ParsedType T = getTypeAnnotation(Tok);
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
@@ -2584,10 +2725,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// then treat __is_signed as an identifier rather than as a keyword.
if (DS.getTypeSpecType() == TST_bool &&
DS.getTypeQualifiers() == DeclSpec::TQ_const &&
- DS.getStorageClassSpec() == DeclSpec::SCS_static) {
- Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();
- Tok.setKind(tok::identifier);
- }
+ DS.getStorageClassSpec() == DeclSpec::SCS_static)
+ TryKeywordIdentFallback(true);
// We're done with the declaration-specifiers.
goto DoneWithDeclSpec;
@@ -2598,7 +2737,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// In C++, check to see if this is a scope specifier like foo::bar::, if
// so handle it as such. This is important for ctor parsing.
if (getLangOpts().CPlusPlus) {
- if (TryAnnotateCXXScopeToken(true)) {
+ if (TryAnnotateCXXScopeToken(EnteringContext)) {
if (!DS.hasTypeSpecifier())
DS.SetTypeSpecError();
goto DoneWithDeclSpec;
@@ -2701,16 +2840,18 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Microsoft single token adornments.
case tok::kw___forceinline: {
- isInvalid = DS.setFunctionSpecInline(Loc);
+ isInvalid = DS.setFunctionSpecForceInline(Loc, PrevSpec, DiagID);
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = Tok.getLocation();
// FIXME: This does not work correctly if it is set to be a declspec
// attribute, and a GNU attribute is simply incorrect.
- DS.getAttributes().addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0, AttributeList::AS_GNU);
+ DS.getAttributes().addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ AttributeList::AS_GNU);
break;
}
+ case tok::kw___sptr:
+ case tok::kw___uptr:
case tok::kw___ptr64:
case tok::kw___ptr32:
case tok::kw___w64:
@@ -2791,18 +2932,18 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// function-specifier
case tok::kw_inline:
- isInvalid = DS.setFunctionSpecInline(Loc);
+ isInvalid = DS.setFunctionSpecInline(Loc, PrevSpec, DiagID);
break;
case tok::kw_virtual:
- isInvalid = DS.setFunctionSpecVirtual(Loc);
+ isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID);
break;
case tok::kw_explicit:
- isInvalid = DS.setFunctionSpecExplicit(Loc);
+ isInvalid = DS.setFunctionSpecExplicit(Loc, PrevSpec, DiagID);
break;
case tok::kw__Noreturn:
if (!getLangOpts().C11)
Diag(Loc, diag::ext_c11_noreturn);
- isInvalid = DS.setFunctionSpecNoreturn(Loc);
+ isInvalid = DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID);
break;
// alignment-specifier
@@ -3168,7 +3309,7 @@ ParseStructDeclaration(ParsingDeclSpec &DS, FieldCallback &Fields) {
ConsumeToken();
ExprResult Res(ParseConstantExpression());
if (Res.isInvalid())
- SkipUntil(tok::semi, true, true);
+ SkipUntil(tok::semi, StopBeforeMatch);
else
DeclaratorInfo.BitfieldSize = Res.release();
}
@@ -3214,12 +3355,6 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
- // Empty structs are an extension in C (C99 6.7.2.1p7).
- if (Tok.is(tok::r_brace)) {
- Diag(Tok, diag::ext_empty_struct_union) << (TagType == TST_union);
- Diag(Tok, diag::warn_empty_struct_union_compat) << (TagType == TST_union);
- }
-
SmallVector<Decl *, 32> FieldDecls;
// While we still have something to read, read the declarations in the struct.
@@ -3276,14 +3411,14 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
ConsumeToken();
if (!Tok.isObjCAtKeyword(tok::objc_defs)) {
Diag(Tok, diag::err_unexpected_at);
- SkipUntil(tok::semi, true);
+ SkipUntil(tok::semi);
continue;
}
ConsumeToken();
ExpectAndConsume(tok::l_paren, diag::err_expected_lparen);
if (!Tok.is(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
- SkipUntil(tok::semi, true);
+ SkipUntil(tok::semi);
continue;
}
SmallVector<Decl *, 16> Fields;
@@ -3302,7 +3437,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
} else {
ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
// Skip to end of block or statement to avoid ext-warning on extra ';'.
- SkipUntil(tok::r_brace, true, true);
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
// If we stopped at a ';', eat it.
if (Tok.is(tok::semi)) ConsumeToken();
}
@@ -3426,7 +3561,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
if (Tok.isNot(tok::l_brace)) {
// Has no name and is not a definition.
// Skip the rest of this declarator, up until the comma or semicolon.
- SkipUntil(tok::comma, true);
+ SkipUntil(tok::comma, StopAtSemi);
return;
}
}
@@ -3438,7 +3573,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
Diag(Tok, diag::err_expected_ident_lbrace);
// Skip the rest of this declarator, up until the comma or semicolon.
- SkipUntil(tok::comma, true);
+ SkipUntil(tok::comma, StopAtSemi);
return;
}
@@ -3556,7 +3691,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
Diag(Tok.getLocation(), diag::err_friend_decl_defines_type)
<< SourceRange(DS.getFriendSpecLoc());
ConsumeBrace();
- SkipUntil(tok::r_brace);
+ SkipUntil(tok::r_brace, StopAtSemi);
TUK = Sema::TUK_Friend;
} else {
TUK = Sema::TUK_Definition;
@@ -3589,7 +3724,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
if (!getLangOpts().CPlusPlus11 || !SS.isSet()) {
// Skip the rest of this declarator, up until the comma or semicolon.
Diag(Tok, diag::err_enum_template);
- SkipUntil(tok::comma, true);
+ SkipUntil(tok::comma, StopAtSemi);
return;
}
@@ -3612,7 +3747,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
Diag(Tok, diag::err_enumerator_unnamed_no_def);
// Skip the rest of this declarator, up until the comma or semicolon.
- SkipUntil(tok::comma, true);
+ SkipUntil(tok::comma, StopAtSemi);
return;
}
@@ -3656,7 +3791,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// definition, consume the entire definition.
if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) {
ConsumeBrace();
- SkipUntil(tok::r_brace);
+ SkipUntil(tok::r_brace, StopAtSemi);
}
DS.SetTypeSpecError();
@@ -3717,7 +3852,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
EqualLoc = ConsumeToken();
AssignedVal = ParseConstantExpression();
if (AssignedVal.isInvalid())
- SkipUntil(tok::comma, tok::r_brace, true, true);
+ SkipUntil(tok::comma, tok::r_brace, StopAtSemi | StopBeforeMatch);
}
// Install the enumerator constant into EnumDecl.
@@ -4145,6 +4280,8 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw___fastcall:
case tok::kw___thiscall:
case tok::kw___w64:
+ case tok::kw___sptr:
+ case tok::kw___uptr:
case tok::kw___ptr64:
case tok::kw___ptr32:
case tok::kw___forceinline:
@@ -4199,6 +4336,15 @@ bool Parser::isConstructorDeclarator() {
return true;
}
+ // A C++11 attribute here signals that we have a constructor, and is an
+ // attribute on the first constructor parameter.
+ if (getLangOpts().CPlusPlus11 &&
+ isCXX11AttributeSpecifier(/*Disambiguate*/ false,
+ /*OuterMightBeMessageSend*/ true)) {
+ TPA.Revert();
+ return true;
+ }
+
// If we need to, enter the specified scope.
DeclaratorScopeObj DeclScopeObj(*this, SS);
if (SS.isSet() && Actions.ShouldEnterDeclaratorScope(getCurScope(), SS))
@@ -4267,7 +4413,8 @@ bool Parser::isConstructorDeclarator() {
void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
bool VendorAttributesAllowed,
bool CXX11AttributesAllowed,
- bool AtomicAllowed) {
+ bool AtomicAllowed,
+ bool IdentifierRequired) {
if (getLangOpts().CPlusPlus11 && CXX11AttributesAllowed &&
isCXX11AttributeSpecifier()) {
ParsedAttributesWithRange attrs(AttrFactory);
@@ -4321,6 +4468,15 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
ParseOpenCLQualifiers(DS);
break;
+ case tok::kw___uptr:
+ // GNU libc headers in C mode use '__uptr' as an identifer which conflicts
+ // with the MS modifier keyword.
+ if (VendorAttributesAllowed && !getLangOpts().CPlusPlus &&
+ IdentifierRequired && DS.isEmpty() && NextToken().is(tok::semi)) {
+ if (TryKeywordIdentFallback(false))
+ continue;
+ }
+ case tok::kw___sptr:
case tok::kw___w64:
case tok::kw___ptr64:
case tok::kw___ptr32:
@@ -4476,7 +4632,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
DeclSpec DS(AttrFactory);
// FIXME: GNU attributes are not allowed here in a new-type-id.
- ParseTypeQualifierListOpt(DS);
+ ParseTypeQualifierListOpt(DS, true, true, true, !D.mayOmitIdentifier());
D.ExtendWithDeclSpec(DS);
// Recursively parse the declarator.
@@ -4636,6 +4792,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// as part of the parameter-declaration-clause.
if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&
!((D.getContext() == Declarator::PrototypeContext ||
+ D.getContext() == Declarator::LambdaExprParameterContext ||
D.getContext() == Declarator::BlockLiteralContext) &&
NextToken().is(tok::r_paren) &&
!D.hasGroupingParens() &&
@@ -4697,6 +4854,17 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken();
goto PastIdentifier;
+ } else if (Tok.is(tok::identifier) && D.diagnoseIdentifier()) {
+ // A virt-specifier isn't treated as an identifier if it appears after a
+ // trailing-return-type.
+ if (D.getContext() != Declarator::TrailingReturnContext ||
+ !isCXX11VirtSpecifier(Tok)) {
+ Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id)
+ << FixItHint::CreateRemoval(Tok.getLocation());
+ D.SetIdentifier(0, Tok.getLocation());
+ ConsumeToken();
+ goto PastIdentifier;
+ }
}
if (Tok.is(tok::l_paren)) {
@@ -4736,8 +4904,15 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
else if (getLangOpts().CPlusPlus) {
if (Tok.is(tok::period) || Tok.is(tok::arrow))
Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
- else
- Diag(Tok, diag::err_expected_unqualified_id) << getLangOpts().CPlusPlus;
+ else {
+ SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
+ if (Tok.isAtStartOfLine() && Loc.isValid())
+ Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
+ << getLangOpts().CPlusPlus;
+ else
+ Diag(Tok, diag::err_expected_unqualified_id)
+ << getLangOpts().CPlusPlus;
+ }
} else
Diag(Tok, diag::err_expected_ident_lparen);
D.SetIdentifier(0, Tok.getLocation());
@@ -4948,7 +5123,6 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
TypeResult TrailingReturnType;
Actions.ActOnStartFunctionDeclarator();
-
/* LocalEndLoc is the end location for the local FunctionTypeLoc.
EndLoc is the end location for the function declarator.
They differ for trailing return types. */
@@ -4969,7 +5143,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
EndLoc = RParenLoc;
} else {
if (Tok.isNot(tok::r_paren))
- ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, EllipsisLoc);
+ ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo,
+ EllipsisLoc);
else if (RequiresArg)
Diag(Tok, diag::err_argument_required_after_attribute);
@@ -5117,7 +5292,7 @@ bool Parser::isFunctionDeclaratorIdentifierList() {
///
void Parser::ParseFunctionDeclaratorIdentifierList(
Declarator &D,
- SmallVector<DeclaratorChunk::ParamInfo, 16> &ParamInfo) {
+ SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo) {
// If there was no identifier specified for the declarator, either we are in
// an abstract-declarator, or we are in a parameter declarator which was found
// to be abstract. In abstract-declarators, identifier lists are not valid:
@@ -5132,7 +5307,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(
// If this isn't an identifier, report the error and skip until ')'.
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
- SkipUntil(tok::r_paren, /*StopAtSemi=*/true, /*DontConsume=*/true);
+ SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
// Forget we parsed anything.
ParamInfo.clear();
return;
@@ -5198,9 +5373,8 @@ void Parser::ParseFunctionDeclaratorIdentifierList(
void Parser::ParseParameterDeclarationClause(
Declarator &D,
ParsedAttributes &FirstArgAttrs,
- SmallVector<DeclaratorChunk::ParamInfo, 16> &ParamInfo,
+ SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
SourceLocation &EllipsisLoc) {
-
while (1) {
if (Tok.is(tok::ellipsis)) {
// FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
@@ -5230,16 +5404,21 @@ void Parser::ParseParameterDeclarationClause(
ParseDeclarationSpecifiers(DS);
- // Parse the declarator. This is "PrototypeContext", because we must
- // accept either 'declarator' or 'abstract-declarator' here.
- Declarator ParmDecl(DS, Declarator::PrototypeContext);
- ParseDeclarator(ParmDecl);
+
+ // Parse the declarator. This is "PrototypeContext" or
+ // "LambdaExprParameterContext", because we must accept either
+ // 'declarator' or 'abstract-declarator' here.
+ Declarator ParmDeclarator(DS,
+ D.getContext() == Declarator::LambdaExprContext ?
+ Declarator::LambdaExprParameterContext :
+ Declarator::PrototypeContext);
+ ParseDeclarator(ParmDeclarator);
// Parse GNU attributes, if present.
- MaybeParseGNUAttributes(ParmDecl);
+ MaybeParseGNUAttributes(ParmDeclarator);
// Remember this parsed parameter in ParamInfo.
- IdentifierInfo *ParmII = ParmDecl.getIdentifier();
+ IdentifierInfo *ParmII = ParmDeclarator.getIdentifier();
// DefArgToks is used when the parsing of default arguments needs
// to be delayed.
@@ -5247,8 +5426,8 @@ void Parser::ParseParameterDeclarationClause(
// If no parameter was specified, verify that *something* was specified,
// otherwise we have a missing type and identifier.
- if (DS.isEmpty() && ParmDecl.getIdentifier() == 0 &&
- ParmDecl.getNumTypeObjects() == 0) {
+ if (DS.isEmpty() && ParmDeclarator.getIdentifier() == 0 &&
+ ParmDeclarator.getNumTypeObjects() == 0) {
// Completely missing, emit error.
Diag(DSStart, diag::err_missing_param);
} else {
@@ -5257,8 +5436,8 @@ void Parser::ParseParameterDeclarationClause(
// Inform the actions module about the parameter declarator, so it gets
// added to the current scope.
- Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
-
+ Decl *Param = Actions.ActOnParamDeclarator(getCurScope(),
+ ParmDeclarator);
// Parse the default argument, if any. We parse the default
// arguments in all dialects; the semantic analysis in
// ActOnParamDefaultArgument will reject the default argument in
@@ -5274,9 +5453,7 @@ void Parser::ParseParameterDeclarationClause(
// FIXME: Can we use a smart pointer for Toks?
DefArgToks = new CachedTokens;
- if (!ConsumeAndStoreUntil(tok::comma, tok::r_paren, *DefArgToks,
- /*StopAtSemi=*/true,
- /*ConsumeFinalToken=*/false)) {
+ if (!ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument)) {
delete DefArgToks;
DefArgToks = 0;
Actions.ActOnParamDefaultArgumentError(Param);
@@ -5309,7 +5486,7 @@ void Parser::ParseParameterDeclarationClause(
DefArgResult = ParseAssignmentExpression();
if (DefArgResult.isInvalid()) {
Actions.ActOnParamDefaultArgumentError(Param);
- SkipUntil(tok::comma, tok::r_paren, true, true);
+ SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);
} else {
// Inform the actions module about the default argument
Actions.ActOnParamDefaultArgument(Param, EqualLoc,
@@ -5319,8 +5496,8 @@ void Parser::ParseParameterDeclarationClause(
}
ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
- ParmDecl.getIdentifierLoc(), Param,
- DefArgToks));
+ ParmDeclarator.getIdentifierLoc(),
+ Param, DefArgToks));
}
// If the next token is a comma, consume it and keep reading arguments.
@@ -5444,7 +5621,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
if (NumElements.isInvalid()) {
D.setInvalidType(true);
// If the expression was invalid, skip it.
- SkipUntil(tok::r_square);
+ SkipUntil(tok::r_square, StopAtSemi);
return;
}
@@ -5541,7 +5718,7 @@ void Parser::ParseAtomicSpecifier(DeclSpec &DS) {
TypeResult Result = ParseTypeName();
if (Result.isInvalid()) {
- SkipUntil(tok::r_paren);
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
}
@@ -5586,6 +5763,10 @@ bool Parser::TryAltiVecVectorTokenOutOfLine() {
Tok.setKind(tok::kw___vector);
return true;
}
+ if (Next.getIdentifierInfo() == Ident_bool) {
+ Tok.setKind(tok::kw___vector);
+ return true;
+ }
return false;
}
}
@@ -5614,6 +5795,10 @@ bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
return true;
}
+ if (Next.getIdentifierInfo() == Ident_bool) {
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ return true;
+ }
break;
default:
break;
@@ -5622,6 +5807,10 @@ bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
DS.isTypeAltiVecVector()) {
isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
return true;
+ } else if ((Tok.getIdentifierInfo() == Ident_bool) &&
+ DS.isTypeAltiVecVector()) {
+ isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID);
+ return true;
}
return false;
}
OpenPOWER on IntegriCloud