Updated to Clang 3.5a.
Change-Id: I8127eb568f674c2e72635b639a3295381fe8af82
diff --git a/lib/Parse/Android.mk b/lib/Parse/Android.mk
index 3f8f456..5bc2200 100644
--- a/lib/Parse/Android.mk
+++ b/lib/Parse/Android.mk
@@ -6,13 +6,11 @@
include $(CLEAR_TBLGEN_VARS)
TBLGEN_TABLES := \
- AttrExprArgs.inc \
- AttrIdentifierArg.inc \
AttrList.inc \
- AttrLateParsed.inc \
AttrParsedAttrList.inc \
- AttrTypeArg.inc \
Attrs.inc \
+ AttrVisitor.inc \
+ AttrParserStringSwitches.inc \
CommentCommandList.inc \
CommentNodes.inc \
DeclNodes.inc \
diff --git a/lib/Parse/CMakeLists.txt b/lib/Parse/CMakeLists.txt
index 08bf4e1..10b146f 100644
--- a/lib/Parse/CMakeLists.txt
+++ b/lib/Parse/CMakeLists.txt
@@ -1,3 +1,9 @@
+set(LLVM_LINK_COMPONENTS
+ MCParser
+ MC
+ Support
+ )
+
add_clang_library(clangParse
ParseAST.cpp
ParseCXXInlineMethods.cpp
@@ -13,23 +19,8 @@
ParseTemplate.cpp
ParseTentative.cpp
Parser.cpp
- )
-add_dependencies(clangParse
- ClangAttrClasses
- ClangAttrIdentifierArg
- ClangAttrLateParsed
- ClangAttrList
- ClangAttrParsedAttrList
- ClangAttrTypeArg
- ClangCommentNodes
- ClangDeclNodes
- ClangDiagnosticCommon
- ClangDiagnosticParse
- ClangStmtNodes
- )
-
-target_link_libraries(clangParse
+ LINK_LIBS
clangBasic
clangAST
clangLex
diff --git a/lib/Parse/ParseAST.cpp b/lib/Parse/ParseAST.cpp
index 5678ece..0f5a1b3 100644
--- a/lib/Parse/ParseAST.cpp
+++ b/lib/Parse/ParseAST.cpp
@@ -23,9 +23,9 @@
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaConsumer.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include <cstdio>
+#include <memory>
using namespace clang;
@@ -36,7 +36,7 @@
const Parser &P;
public:
PrettyStackTraceParserEntry(const Parser &p) : P(p) {}
- virtual void print(raw_ostream &OS) const;
+ void print(raw_ostream &OS) const override;
};
/// If a crash happens while the parser is active, print out a line indicating
@@ -88,7 +88,8 @@
CodeCompleteConsumer *CompletionConsumer,
bool SkipFunctionBodies) {
- OwningPtr<Sema> S(new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer));
+ std::unique_ptr<Sema> S(
+ new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer));
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get());
@@ -109,8 +110,8 @@
ASTConsumer *Consumer = &S.getASTConsumer();
- OwningPtr<Parser> ParseOP(new Parser(S.getPreprocessor(), S,
- SkipFunctionBodies));
+ std::unique_ptr<Parser> ParseOP(
+ new Parser(S.getPreprocessor(), S, SkipFunctionBodies));
Parser &P = *ParseOP.get();
PrettyStackTraceParserEntry CrashInfo(P);
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 7792305..4cf87e5 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -19,13 +19,6 @@
#include "clang/Sema/Scope.h"
using namespace clang;
-/// Get the FunctionDecl for a function or function template decl.
-static FunctionDecl *getFunctionDecl(Decl *D) {
- if (FunctionDecl *fn = dyn_cast<FunctionDecl>(D))
- return fn;
- return cast<FunctionTemplateDecl>(D)->getTemplatedDecl();
-}
-
/// ParseCXXInlineMethodDef - We parsed and verified that the specified
/// 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.
@@ -69,9 +62,7 @@
D.complete(FnD);
- if (Tok.is(tok::equal)) {
- ConsumeToken();
-
+ if (TryConsumeToken(tok::equal)) {
if (!FnD) {
SkipUntil(tok::semi);
return 0;
@@ -79,20 +70,16 @@
bool Delete = false;
SourceLocation KWLoc;
- if (Tok.is(tok::kw_delete)) {
- Diag(Tok, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_deleted_function :
- diag::ext_deleted_function);
-
- KWLoc = ConsumeToken();
+ if (TryConsumeToken(tok::kw_delete, KWLoc)) {
+ Diag(KWLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_deleted_function
+ : diag::ext_deleted_function);
Actions.SetDeclDeleted(FnD, KWLoc);
Delete = true;
- } else if (Tok.is(tok::kw_default)) {
- Diag(Tok, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_defaulted_function :
- diag::ext_defaulted_function);
-
- KWLoc = ConsumeToken();
+ } else if (TryConsumeToken(tok::kw_default, KWLoc)) {
+ Diag(KWLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_defaulted_function
+ : diag::ext_defaulted_function);
Actions.SetDeclDefaulted(FnD, KWLoc);
} else {
llvm_unreachable("function definition after = not 'delete' or 'default'");
@@ -102,9 +89,9 @@
Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)
<< Delete;
SkipUntil(tok::semi);
- } else {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- Delete ? "delete" : "default", tok::semi);
+ } else if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ Delete ? "delete" : "default")) {
+ SkipUntil(tok::semi);
}
return FnD;
@@ -115,9 +102,9 @@
// the tokens and store them for parsing at the end of the translation unit.
if (getLangOpts().DelayedTemplateParsing &&
DefinitionKind == FDK_Definition &&
- !D.getDeclSpec().isConstexprSpecified() &&
- !(FnD && getFunctionDecl(FnD) &&
- getFunctionDecl(FnD)->getResultType()->getContainedAutoType()) &&
+ !D.getDeclSpec().isConstexprSpecified() &&
+ !(FnD && FnD->getAsFunction() &&
+ FnD->getAsFunction()->getReturnType()->getContainedAutoType()) &&
((Actions.CurContext->isDependentContext() ||
(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
TemplateInfo.Kind != ParsedTemplateInfo::ExplicitSpecialization)) &&
@@ -127,7 +114,7 @@
LexTemplateFunctionForLateParsing(Toks);
if (FnD) {
- FunctionDecl *FD = getFunctionDecl(FnD);
+ FunctionDecl *FD = FnD->getAsFunction();
Actions.CheckForFunctionRedefinition(FD);
Actions.MarkAsLateParsedTemplate(FD, FnD, Toks);
}
@@ -179,7 +166,7 @@
// If you remove this, you can remove the code that clears the flag
// after parsing the member.
if (D.getDeclSpec().isFriendSpecified()) {
- FunctionDecl *FD = getFunctionDecl(FnD);
+ FunctionDecl *FD = FnD->getAsFunction();
Actions.CheckForFunctionRedefinition(FD);
FD->setLateTemplateParsed(true);
}
@@ -348,9 +335,7 @@
if (DefArgResult.isInvalid())
Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
else {
- if (Tok.is(tok::cxx_defaultarg_end))
- ConsumeToken();
- else {
+ if (!TryConsumeToken(tok::cxx_defaultarg_end)) {
// The last two tokens are the terminator and the saved value of
// Tok; the last token in the default argument is the one before
// those.
@@ -464,7 +449,8 @@
ParseFunctionStatementBody(LM.D, FnScope);
// Clear the late-template-parsed bit if we set it before.
- if (LM.D) getFunctionDecl(LM.D)->setLateTemplateParsed(false);
+ if (LM.D)
+ LM.D->getAsFunction()->setLateTemplateParsed(false);
if (Tok.getLocation() != origLoc) {
// Due to parsing error, we either went over the cached tokens or
@@ -536,10 +522,13 @@
SourceLocation EqualLoc;
+ Actions.ActOnStartCXXInClassMemberInitializer();
+
ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false,
EqualLoc);
- Actions.ActOnCXXInClassMemberInitializer(MI.Field, EqualLoc, Init.release());
+ Actions.ActOnFinishCXXInClassMemberInitializer(MI.Field, EqualLoc,
+ Init.release());
// The next token should be our artificial terminating EOF token.
if (Tok.isNot(tok::eof)) {
@@ -580,6 +569,9 @@
switch (Tok.getKind()) {
case tok::eof:
+ case tok::annot_module_begin:
+ case tok::annot_module_end:
+ case tok::annot_module_include:
// Ran out of tokens.
return false;
@@ -675,7 +667,7 @@
/*StopAtSemi=*/true,
/*ConsumeFinalToken=*/false);
if (Tok.isNot(tok::l_brace))
- return Diag(Tok.getLocation(), diag::err_expected_lbrace);
+ return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace;
Toks.push_back(Tok);
ConsumeBrace();
@@ -708,8 +700,8 @@
Toks.push_back(Tok);
ConsumeParen();
if (!ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/true)) {
- Diag(Tok.getLocation(), diag::err_expected_rparen);
- Diag(OpenLoc, diag::note_matching) << "(";
+ Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
+ Diag(OpenLoc, diag::note_matching) << tok::l_paren;
return true;
}
}
@@ -756,13 +748,15 @@
/*ConsumeFinalToken=*/false)) {
// We're not just missing the initializer, we're also missing the
// function body!
- return Diag(Tok.getLocation(), diag::err_expected_lbrace);
+ return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace;
}
} else if (Tok.isNot(tok::l_paren) && Tok.isNot(tok::l_brace)) {
// We found something weird in a mem-initializer-id.
- return Diag(Tok.getLocation(), getLangOpts().CPlusPlus11
- ? diag::err_expected_lparen_or_lbrace
- : diag::err_expected_lparen);
+ if (getLangOpts().CPlusPlus11)
+ return Diag(Tok.getLocation(), diag::err_expected_either)
+ << tok::l_paren << tok::l_brace;
+ else
+ return Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
}
tok::TokenKind kind = Tok.getKind();
@@ -784,11 +778,10 @@
// Grab the initializer (or the subexpression of the template argument).
// FIXME: If we support lambdas here, we'll need to set StopAtSemi to false
// if we might be inside the braces of a lambda-expression.
- if (!ConsumeAndStoreUntil(IsLParen ? tok::r_paren : tok::r_brace,
- Toks, /*StopAtSemi=*/true)) {
- Diag(Tok, IsLParen ? diag::err_expected_rparen :
- diag::err_expected_rbrace);
- Diag(OpenLoc, diag::note_matching) << (IsLParen ? "(" : "{");
+ tok::TokenKind CloseKind = IsLParen ? tok::r_paren : tok::r_brace;
+ if (!ConsumeAndStoreUntil(CloseKind, Toks, /*StopAtSemi=*/true)) {
+ Diag(Tok, diag::err_expected) << CloseKind;
+ Diag(OpenLoc, diag::note_matching) << kind;
return true;
}
@@ -822,7 +815,8 @@
ConsumeBrace();
return false;
} else if (!MightBeTemplateArgument) {
- return Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
+ return Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace
+ << tok::comma;
}
}
}
@@ -965,6 +959,9 @@
goto consume_token;
case tok::eof:
+ case tok::annot_module_begin:
+ case tok::annot_module_end:
+ case tok::annot_module_include:
// Ran out of tokens.
return false;
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 7b80934..331c5e4 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -13,10 +13,12 @@
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/Attributes.h"
#include "clang/Basic/CharInfo.h"
-#include "clang/Basic/OpenCL.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
@@ -69,9 +71,11 @@
/// isAttributeLateParsed - Return true if the attribute has arguments that
/// require late parsing.
static bool isAttributeLateParsed(const IdentifierInfo &II) {
+#define CLANG_ATTR_LATE_PARSED_LIST
return llvm::StringSwitch<bool>(II.getName())
-#include "clang/Parse/AttrLateParsed.inc"
+#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(false);
+#undef CLANG_ATTR_LATE_PARSED_LIST
}
/// ParseGNUAttributes - Parse a non-empty attributes list.
@@ -117,7 +121,8 @@
/// We follow the C++ model, but don't allow junk after the identifier.
void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
SourceLocation *endLoc,
- LateParsedAttrList *LateAttrs) {
+ LateParsedAttrList *LateAttrs,
+ Declarator *D) {
assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
while (Tok.is(tok::kw___attribute)) {
@@ -132,49 +137,54 @@
return;
}
// Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") ))
- while (Tok.is(tok::identifier) || isDeclarationSpecifier() ||
- Tok.is(tok::comma)) {
- if (Tok.is(tok::comma)) {
- // allows for empty/non-empty attributes. ((__vector_size__(16),,,,))
- ConsumeToken();
+ while (true) {
+ // Allow empty/non-empty attributes. ((__vector_size__(16),,,,))
+ if (TryConsumeToken(tok::comma))
continue;
- }
- // we have an identifier or declaration specifier (const, int, etc.)
+
+ // Expect an identifier or declaration specifier (const, int, etc.)
+ if (Tok.isNot(tok::identifier) && !isDeclarationSpecifier())
+ break;
+
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- if (Tok.is(tok::l_paren)) {
- // handle "parameterized" attributes
- if (LateAttrs && isAttributeLateParsed(*AttrName)) {
- LateParsedAttribute *LA =
- new LateParsedAttribute(this, *AttrName, AttrNameLoc);
- LateAttrs->push_back(LA);
-
- // Attributes in a class are parsed at the end of the class, along
- // with other late-parsed declarations.
- if (!ClassStack.empty() && !LateAttrs->parseSoon())
- getCurrentClass().LateParsedDeclarations.push_back(LA);
-
- // consume everything up to and including the matching right parens
- ConsumeAndStoreUntil(tok::r_paren, LA->Toks, true, false);
-
- Token Eof;
- Eof.startToken();
- Eof.setLocation(Tok.getLocation());
- LA->Toks.push_back(Eof);
- } else {
- ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc,
- 0, SourceLocation(), AttributeList::AS_GNU);
- }
- } else {
+ if (Tok.isNot(tok::l_paren)) {
attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
AttributeList::AS_GNU);
+ continue;
}
+
+ // Handle "parameterized" attributes
+ if (!LateAttrs || !isAttributeLateParsed(*AttrName)) {
+ ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc, 0,
+ SourceLocation(), AttributeList::AS_GNU, D);
+ continue;
+ }
+
+ // Handle attributes with arguments that require late parsing.
+ LateParsedAttribute *LA =
+ new LateParsedAttribute(this, *AttrName, AttrNameLoc);
+ LateAttrs->push_back(LA);
+
+ // Attributes in a class are parsed at the end of the class, along
+ // with other late-parsed declarations.
+ if (!ClassStack.empty() && !LateAttrs->parseSoon())
+ getCurrentClass().LateParsedDeclarations.push_back(LA);
+
+ // consume everything up to and including the matching right parens
+ ConsumeAndStoreUntil(tok::r_paren, LA->Toks, true, false);
+
+ Token Eof;
+ Eof.startToken();
+ Eof.setLocation(Tok.getLocation());
+ LA->Toks.push_back(Eof);
}
- if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+
+ if (ExpectAndConsume(tok::r_paren))
SkipUntil(tok::r_paren, StopAtSemi);
SourceLocation Loc = Tok.getLocation();
- if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+ if (ExpectAndConsume(tok::r_paren))
SkipUntil(tok::r_paren, StopAtSemi);
if (endLoc)
*endLoc = Loc;
@@ -190,16 +200,30 @@
/// \brief Determine whether the given attribute has an identifier argument.
static bool attributeHasIdentifierArg(const IdentifierInfo &II) {
+#define CLANG_ATTR_IDENTIFIER_ARG_LIST
return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
-#include "clang/Parse/AttrIdentifierArg.inc"
+#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(false);
+#undef CLANG_ATTR_IDENTIFIER_ARG_LIST
}
/// \brief Determine whether the given attribute parses a type argument.
static bool attributeIsTypeArgAttr(const IdentifierInfo &II) {
+#define CLANG_ATTR_TYPE_ARG_LIST
return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
-#include "clang/Parse/AttrTypeArg.inc"
+#include "clang/Parse/AttrParserStringSwitches.inc"
.Default(false);
+#undef CLANG_ATTR_TYPE_ARG_LIST
+}
+
+/// \brief Determine whether the given attribute requires parsing its arguments
+/// in an unevaluated context or not.
+static bool attributeParsedArgsUnevaluated(const IdentifierInfo &II) {
+#define CLANG_ATTR_ARG_CONTEXT_LIST
+ return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
+#include "clang/Parse/AttrParserStringSwitches.inc"
+ .Default(false);
+#undef CLANG_ATTR_ARG_CONTEXT_LIST
}
IdentifierLoc *Parser::ParseIdentifierLoc() {
@@ -237,54 +261,19 @@
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,
- SourceLocation AttrNameLoc,
- ParsedAttributes &Attrs,
- SourceLocation *EndLoc,
- IdentifierInfo *ScopeName,
- SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax) {
-
- 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.
- // 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 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 (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;
- }
-
+void Parser::ParseAttributeArgsCommon(
+ IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc, AttributeList::Syntax Syntax) {
// Ignore the left paren location for now.
ConsumeParen();
ArgsVector ArgExprs;
-
if (Tok.is(tok::identifier)) {
// If this attribute wants an 'identifier' argument, make it so.
bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName);
+ AttributeList::Kind AttrKind =
+ AttributeList::getKind(AttrName, ScopeName, Syntax);
// 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.
@@ -304,112 +293,120 @@
ConsumeToken();
// Parse the non-empty comma-separated list of expressions.
- while (1) {
+ do {
+ std::unique_ptr<EnterExpressionEvaluationContext> Unevaluated;
+ if (attributeParsedArgsUnevaluated(*AttrName))
+ Unevaluated.reset(
+ new EnterExpressionEvaluationContext(Actions, Sema::Unevaluated));
+
ExprResult ArgExpr(ParseAssignmentExpression());
if (ArgExpr.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
return;
}
ArgExprs.push_back(ArgExpr.release());
- if (Tok.isNot(tok::comma))
- break;
- ConsumeToken(); // Eat the comma, move to the next argument
- }
+ // Eat the comma, move to the next argument
+ } while (TryConsumeToken(tok::comma));
}
SourceLocation RParen = Tok.getLocation();
- if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
+ if (!ExpectAndConsume(tok::r_paren)) {
SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc;
Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc,
ArgExprs.data(), ArgExprs.size(), Syntax);
}
+
+ if (EndLoc)
+ *EndLoc = RParen;
}
-/// \brief Parses a single argument for a declspec, including the
-/// surrounding parens.
-void Parser::ParseMicrosoftDeclSpecWithSingleArg(IdentifierInfo *AttrName,
- SourceLocation AttrNameLoc,
- ParsedAttributes &Attrs)
-{
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- AttrName->getNameStart(), tok::r_paren))
- return;
+/// Parse the arguments to a parameterized GNU attribute or
+/// a C++11 attribute in "gnu" namespace.
+void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs,
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax,
+ Declarator *D) {
- ExprResult ArgExpr(ParseConstantExpression());
- if (ArgExpr.isInvalid()) {
- T.skipToEnd();
+ 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.
+ // 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;
}
- ArgsUnion ExprList = ArgExpr.take();
- Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, &ExprList, 1,
- AttributeList::AS_Declspec);
- T.consumeClose();
+ if (AttrKind == AttributeList::AT_ObjCBridgeRelated) {
+ ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc);
+ return;
+ }
+
+ // Type safety attributes have their own grammar.
+ 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;
+ }
+
+ // These may refer to the function arguments, but need to be parsed early to
+ // participate in determining whether it's a redeclaration.
+ std::unique_ptr<ParseScope> PrototypeScope;
+ if (AttrName->isStr("enable_if") && D && D->isFunctionDeclarator()) {
+ DeclaratorChunk::FunctionTypeInfo FTI = D->getFunctionTypeInfo();
+ PrototypeScope.reset(new ParseScope(this, Scope::FunctionPrototypeScope |
+ Scope::FunctionDeclarationScope |
+ Scope::DeclScope));
+ for (unsigned i = 0; i != FTI.NumParams; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
+ Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param);
+ }
+ }
+
+ ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
+ ScopeLoc, Syntax);
}
-/// \brief Determines whether a declspec is a "simple" one requiring no
-/// arguments.
-bool Parser::IsSimpleMicrosoftDeclSpec(IdentifierInfo *Ident) {
- return llvm::StringSwitch<bool>(Ident->getName())
- .Case("dllimport", true)
- .Case("dllexport", true)
- .Case("noreturn", true)
- .Case("nothrow", true)
- .Case("noinline", true)
- .Case("naked", true)
- .Case("appdomain", true)
- .Case("process", true)
- .Case("jitintrinsic", true)
- .Case("noalias", true)
- .Case("restrict", true)
- .Case("novtable", true)
- .Case("selectany", true)
- .Case("thread", true)
- .Case("safebuffers", true )
- .Default(false);
-}
+bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs) {
+ // If the attribute isn't known, we will not attempt to parse any
+ // arguments.
+ if (!hasAttribute(AttrSyntax::Declspec, nullptr, AttrName,
+ getTargetInfo().getTriple(), getLangOpts())) {
+ // Eat the left paren, then skip to the ending right paren.
+ ConsumeParen();
+ SkipUntil(tok::r_paren);
+ return false;
+ }
-/// \brief Attempts to parse a declspec which is not simple (one that takes
-/// parameters). Will return false if we properly handled the declspec, or
-/// true if it is an unknown declspec.
-void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident,
- SourceLocation Loc,
- ParsedAttributes &Attrs) {
- // Try to handle the easy case first -- these declspecs all take a single
- // parameter as their argument.
- if (llvm::StringSwitch<bool>(Ident->getName())
- .Case("uuid", true)
- .Case("align", true)
- .Case("allocate", true)
- .Default(false)) {
- ParseMicrosoftDeclSpecWithSingleArg(Ident, Loc, Attrs);
- } else if (Ident->getName() == "deprecated") {
- // The deprecated declspec has an optional single argument, so we will
- // check for a l-paren to decide whether we should parse an argument or
- // not.
- if (Tok.getKind() == tok::l_paren)
- ParseMicrosoftDeclSpecWithSingleArg(Ident, Loc, Attrs);
- else
- Attrs.addNew(Ident, Loc, 0, Loc, 0, 0, AttributeList::AS_Declspec);
- } else if (Ident->getName() == "property") {
+ if (AttrName->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
// must be named get or put.
- if (Tok.isNot(tok::l_paren)) {
- Diag(Tok.getLocation(), diag::err_expected_lparen_after)
- << Ident->getNameStart();
- return;
- }
+
BalancedDelimiterTracker T(*this, tok::l_paren);
T.expectAndConsume(diag::err_expected_lparen_after,
- Ident->getNameStart(), tok::r_paren);
+ AttrName->getNameStart(), tok::r_paren);
enum AccessorKind {
AK_Invalid = -1,
- AK_Put = 0, AK_Get = 1 // indices into AccessorNames
+ AK_Put = 0,
+ AK_Get = 1 // indices into AccessorNames
};
- IdentifierInfo *AccessorNames[] = { 0, 0 };
+ IdentifierInfo *AccessorNames[] = {0, 0};
bool HasInvalidAccessor = false;
// Parse the accessor specifications.
@@ -419,7 +416,7 @@
// If the user wrote a completely empty list, use a special diagnostic.
if (Tok.is(tok::r_paren) && !HasInvalidAccessor &&
AccessorNames[AK_Put] == 0 && AccessorNames[AK_Get] == 0) {
- Diag(Loc, diag::err_ms_property_no_getter_or_putter);
+ Diag(AttrNameLoc, diag::err_ms_property_no_getter_or_putter);
break;
}
@@ -435,39 +432,38 @@
} else if (KindStr == "put") {
Kind = AK_Put;
- // Recover from the common mistake of using 'set' instead of 'put'.
+ // Recover from the common mistake of using 'set' instead of 'put'.
} else if (KindStr == "set") {
Diag(KindLoc, diag::err_ms_property_has_set_accessor)
- << FixItHint::CreateReplacement(KindLoc, "put");
+ << FixItHint::CreateReplacement(KindLoc, "put");
Kind = AK_Put;
- // Handle the mistake of forgetting the accessor kind by skipping
- // this accessor.
+ // Handle the mistake of forgetting the accessor kind by skipping
+ // this accessor.
} else if (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)) {
Diag(KindLoc, diag::err_ms_property_missing_accessor_kind);
ConsumeToken();
HasInvalidAccessor = true;
goto next_property_accessor;
- // Otherwise, complain about the unknown accessor kind.
+ // Otherwise, complain about the unknown accessor kind.
} else {
Diag(KindLoc, diag::err_ms_property_unknown_accessor);
HasInvalidAccessor = true;
Kind = AK_Invalid;
// Try to keep parsing unless it doesn't look like an accessor spec.
- if (!NextToken().is(tok::equal)) break;
+ if (!NextToken().is(tok::equal))
+ break;
}
// Consume the identifier.
ConsumeToken();
// Consume the '='.
- if (Tok.is(tok::equal)) {
- ConsumeToken();
- } else {
+ if (!TryConsumeToken(tok::equal)) {
Diag(Tok.getLocation(), diag::err_ms_property_expected_equal)
- << KindStr;
+ << KindStr;
break;
}
@@ -489,41 +485,29 @@
next_property_accessor:
// Keep processing accessors until we run out.
- if (Tok.is(tok::comma)) {
- ConsumeAnyToken();
+ if (TryConsumeToken(tok::comma))
continue;
// If we run into the ')', stop without consuming it.
- } else if (Tok.is(tok::r_paren)) {
+ if (Tok.is(tok::r_paren))
break;
- } else {
- Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen);
- break;
- }
+
+ Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen);
+ break;
}
// Only add the property attribute if it was well-formed.
- if (!HasInvalidAccessor) {
- Attrs.addNewPropertyAttr(Ident, Loc, 0, SourceLocation(),
+ if (!HasInvalidAccessor)
+ Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, 0, SourceLocation(),
AccessorNames[AK_Get], AccessorNames[AK_Put],
AttributeList::AS_Declspec);
- }
T.skipToEnd();
- } else {
- // We don't recognize this as a valid declspec, but instead of creating the
- // attribute and allowing sema to warn about it, we will warn here instead.
- // This is because some attributes have multiple spellings, but we need to
- // disallow that for declspecs (such as align vs aligned). If we made the
- // attribute, we'd have to split the valid declspec spelling logic into
- // both locations.
- Diag(Loc, diag::warn_ms_declspec_unknown) << Ident;
-
- // If there's an open paren, we should eat the open and close parens under
- // the assumption that this unknown declspec has parameters.
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (!T.consumeOpen())
- T.skipToEnd();
+ return !HasInvalidAccessor;
}
+
+ ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr,
+ SourceLocation(), AttributeList::AS_Declspec);
+ return true;
}
/// [MS] decl-specifier:
@@ -543,7 +527,11 @@
// An empty declspec is perfectly legal and should not warn. Additionally,
// you can specify multiple attributes per declspec.
- while (Tok.getKind() != tok::r_paren) {
+ while (Tok.isNot(tok::r_paren)) {
+ // Attribute not present.
+ if (TryConsumeToken(tok::comma))
+ continue;
+
// We expect either a well-known identifier or a generic string. Anything
// else is a malformed declspec.
bool IsString = Tok.getKind() == tok::string_literal ? true : false;
@@ -571,17 +559,19 @@
AttrNameLoc = ConsumeToken();
}
- if (IsString || IsSimpleMicrosoftDeclSpec(AttrName))
- // If we have a generic string, we will allow it because there is no
- // documented list of allowable string declspecs, but we know they exist
- // (for instance, SAL declspecs in older versions of MSVC).
- //
- // Alternatively, if the identifier is a simple one, then it requires no
- // arguments and can be turned into an attribute directly.
+ bool AttrHandled = false;
+
+ // Parse attribute arguments.
+ if (Tok.is(tok::l_paren))
+ AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs);
+ else if (AttrName->getName() == "property")
+ // The property attribute must have an argument list.
+ Diag(Tok.getLocation(), diag::err_expected_lparen_after)
+ << AttrName->getName();
+
+ if (!AttrHandled)
Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
AttributeList::AS_Declspec);
- else
- ParseComplexMicrosoftDeclSpec(AttrName, AttrNameLoc, Attrs);
}
T.consumeClose();
}
@@ -620,56 +610,11 @@
}
}
-void Parser::ParseOpenCLQualifiers(DeclSpec &DS) {
- // FIXME: The mapping from attribute spelling to semantics should be
- // performed in Sema, not here.
- SourceLocation Loc = Tok.getLocation();
- switch(Tok.getKind()) {
- // OpenCL qualifiers:
- case tok::kw___private:
- case tok::kw_private:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("address_space"), Loc, 0);
- break;
-
- case tok::kw___global:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_global);
- break;
-
- case tok::kw___local:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_local);
- break;
-
- case tok::kw___constant:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_constant);
- break;
-
- case tok::kw___read_only:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_read_only);
- break;
-
- case tok::kw___write_only:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_write_only);
- break;
-
- case tok::kw___read_write:
- DS.getAttributes().addNewInteger(
- Actions.getASTContext(),
- PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_read_write);
- break;
- default: break;
- }
+void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) {
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+ SourceLocation AttrNameLoc = Tok.getLocation();
+ Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ AttributeList::AS_Keyword);
}
/// \brief Parse a version number.
@@ -812,7 +757,7 @@
// Opening '('.
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.consumeOpen()) {
- Diag(Tok, diag::err_expected_lparen);
+ Diag(Tok, diag::err_expected) << tok::l_paren;
return;
}
@@ -825,8 +770,10 @@
IdentifierLoc *Platform = ParseIdentifierLoc();
// Parse the ',' following the platform name.
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
+ }
// If we haven't grabbed the pointers for the identifiers
// "introduced", "deprecated", and "obsoleted", do so now.
@@ -855,17 +802,11 @@
<< Keyword << SourceRange(UnavailableLoc);
}
UnavailableLoc = KeywordLoc;
-
- if (Tok.isNot(tok::comma))
- break;
-
- ConsumeToken();
continue;
}
if (Tok.isNot(tok::equal)) {
- Diag(Tok, diag::err_expected_equal_after)
- << Keyword;
+ Diag(Tok, diag::err_expected_after) << Keyword << tok::equal;
SkipUntil(tok::r_paren, StopAtSemi);
return;
}
@@ -915,11 +856,7 @@
<< Keyword << VersionRange;
}
- if (Tok.isNot(tok::comma))
- break;
-
- ConsumeToken();
- } while (true);
+ } while (TryConsumeToken(tok::comma));
// Closing ')'.
if (T.consumeClose())
@@ -959,6 +896,86 @@
AttributeList::AS_GNU);
}
+/// \brief Parse the contents of the "objc_bridge_related" attribute.
+/// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')'
+/// related_class:
+/// Identifier
+///
+/// opt-class_method:
+/// Identifier: | <empty>
+///
+/// opt-instance_method:
+/// Identifier | <empty>
+///
+void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
+ SourceLocation ObjCBridgeRelatedLoc,
+ ParsedAttributes &attrs,
+ SourceLocation *endLoc) {
+ // Opening '('.
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.consumeOpen()) {
+ Diag(Tok, diag::err_expected) << tok::l_paren;
+ return;
+ }
+
+ // Parse the related class name.
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_objcbridge_related_expected_related_class);
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+ IdentifierLoc *RelatedClass = ParseIdentifierLoc();
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+
+ // Parse optional class method name.
+ IdentifierLoc *ClassMethod = 0;
+ if (Tok.is(tok::identifier)) {
+ ClassMethod = ParseIdentifierLoc();
+ if (!TryConsumeToken(tok::colon)) {
+ Diag(Tok, diag::err_objcbridge_related_selector_name);
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+ }
+ if (!TryConsumeToken(tok::comma)) {
+ if (Tok.is(tok::colon))
+ Diag(Tok, diag::err_objcbridge_related_selector_name);
+ else
+ Diag(Tok, diag::err_expected) << tok::comma;
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+
+ // Parse optional instance method name.
+ IdentifierLoc *InstanceMethod = 0;
+ if (Tok.is(tok::identifier))
+ InstanceMethod = ParseIdentifierLoc();
+ else if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::err_expected) << tok::r_paren;
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+
+ // Closing ')'.
+ if (T.consumeClose())
+ return;
+
+ if (endLoc)
+ *endLoc = T.getCloseLocation();
+
+ // Record this attribute
+ attrs.addNew(&ObjCBridgeRelated,
+ SourceRange(ObjCBridgeRelatedLoc, T.getCloseLocation()),
+ 0, ObjCBridgeRelatedLoc,
+ RelatedClass,
+ ClassMethod,
+ InstanceMethod,
+ AttributeList::AS_GNU);
+
+}
// Late Parsed Attributes:
// See other examples of late parsing in lib/Parse/ParseCXXInlineMethods
@@ -1038,13 +1055,6 @@
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- if (OnDefinition && !IsThreadSafetyAttribute(LA.AttrName.getName())) {
- // FIXME: Do not warn on C++11 attributes, once we start supporting
- // them here.
- Diag(Tok, diag::warn_attribute_on_function_definition)
- << LA.AttrName.getName();
- }
-
ParsedAttributes Attrs(AttrFactory);
SourceLocation endLoc;
@@ -1071,7 +1081,7 @@
Actions.ActOnReenterFunctionContext(Actions.CurScope, D);
ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
- 0, SourceLocation(), AttributeList::AS_GNU);
+ 0, SourceLocation(), AttributeList::AS_GNU, 0);
if (HasFunScope) {
Actions.ActOnExitFunctionContext();
@@ -1084,15 +1094,20 @@
// If there are multiple decls, then the decl cannot be within the
// function scope.
ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
- 0, SourceLocation(), AttributeList::AS_GNU);
+ 0, SourceLocation(), AttributeList::AS_GNU, 0);
}
} else {
Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName();
}
- for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i) {
+ const AttributeList *AL = Attrs.getList();
+ if (OnDefinition && AL && !AL->isCXX11Attribute() &&
+ AL->isKnownToGCC())
+ Diag(Tok, diag::warn_attribute_on_function_definition)
+ << &LA.AttrName;
+
+ for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i)
Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.Decls[i], Attrs);
- }
if (Tok.getLocation() != OrigLoc) {
// Due to a parsing error, we either went over the cached tokens or
@@ -1106,79 +1121,6 @@
}
}
-/// \brief Wrapper around a case statement checking if AttrName is
-/// one of the thread safety attributes
-bool Parser::IsThreadSafetyAttribute(StringRef AttrName) {
- return llvm::StringSwitch<bool>(AttrName)
- .Case("guarded_by", true)
- .Case("guarded_var", true)
- .Case("pt_guarded_by", true)
- .Case("pt_guarded_var", true)
- .Case("lockable", true)
- .Case("scoped_lockable", true)
- .Case("no_thread_safety_analysis", true)
- .Case("acquired_after", true)
- .Case("acquired_before", true)
- .Case("exclusive_lock_function", true)
- .Case("shared_lock_function", true)
- .Case("exclusive_trylock_function", true)
- .Case("shared_trylock_function", true)
- .Case("unlock_function", true)
- .Case("lock_returned", true)
- .Case("locks_excluded", true)
- .Case("exclusive_locks_required", true)
- .Case("shared_locks_required", true)
- .Default(false);
-}
-
-/// \brief Parse the contents of thread safety attributes. These
-/// should always be parsed as an expression list.
-///
-/// We need to special case the parsing due to the fact that if the first token
-/// of the first argument is an identifier, the main parse loop will store
-/// that token as a "parameter" and the rest of
-/// the arguments will be added to a list of "arguments". However,
-/// subsequent tokens in the first argument are lost. We instead parse each
-/// argument as an expression and add all arguments to the list of "arguments".
-/// In future, we will take advantage of this special case to also
-/// deal with some argument scoping issues here (for example, referring to a
-/// function parameter in the attribute on that function).
-void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName,
- SourceLocation AttrNameLoc,
- ParsedAttributes &Attrs,
- SourceLocation *EndLoc) {
- assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
-
- BalancedDelimiterTracker T(*this, tok::l_paren);
- T.consumeOpen();
-
- ArgsVector ArgExprs;
- bool ArgExprsOk = true;
-
- // now parse the list of expressions
- while (Tok.isNot(tok::r_paren)) {
- EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
- ExprResult ArgExpr(ParseAssignmentExpression());
- if (ArgExpr.isInvalid()) {
- ArgExprsOk = false;
- T.consumeClose();
- break;
- } else {
- ArgExprs.push_back(ArgExpr.release());
- }
- if (Tok.isNot(tok::comma))
- break;
- ConsumeToken(); // Eat the comma, move to the next argument
- }
- // Match the ')'.
- if (ArgExprsOk && !T.consumeClose()) {
- Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc, ArgExprs.data(),
- ArgExprs.size(), AttributeList::AS_GNU);
- }
- if (EndLoc)
- *EndLoc = T.getCloseLocation();
-}
-
void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
@@ -1189,18 +1131,16 @@
T.consumeOpen();
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
T.skipToEnd();
return;
}
IdentifierLoc *ArgumentKind = ParseIdentifierLoc();
- if (Tok.isNot(tok::comma)) {
- Diag(Tok, diag::err_expected_comma);
+ if (ExpectAndConsume(tok::comma)) {
T.skipToEnd();
return;
}
- ConsumeToken();
SourceRange MatchingCTypeRange;
TypeResult MatchingCType = ParseTypeName(&MatchingCTypeRange);
@@ -1211,10 +1151,9 @@
bool LayoutCompatible = false;
bool MustBeNull = false;
- while (Tok.is(tok::comma)) {
- ConsumeToken();
+ while (TryConsumeToken(tok::comma)) {
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
T.skipToEnd();
return;
}
@@ -1508,8 +1447,7 @@
// This declaration isn't over yet. Keep skipping.
continue;
}
- if (Tok.is(tok::semi))
- ConsumeToken();
+ TryConsumeToken(tok::semi);
return;
case tok::l_square:
@@ -1562,6 +1500,9 @@
break;
case tok::eof:
+ case tok::annot_module_begin:
+ case tok::annot_module_end:
+ case tok::annot_module_include:
return;
default:
@@ -1632,7 +1573,8 @@
} else {
if (Tok.is(tok::l_brace)) {
Diag(Tok, diag::err_function_definition_not_allowed);
- SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
+ SkipMalformedDecl();
+ return DeclGroupPtrTy();
}
}
}
@@ -1648,9 +1590,8 @@
// don't need to parse the container in advance.
if (FRI && (Tok.is(tok::colon) || isTokIdentifier_in())) {
bool IsForRangeLoop = false;
- if (Tok.is(tok::colon)) {
+ if (TryConsumeToken(tok::colon, FRI->ColonLoc)) {
IsForRangeLoop = true;
- FRI->ColonLoc = ConsumeToken();
if (Tok.is(tok::l_brace))
FRI->RangeExpr = ParseBraceInitializer();
else
@@ -1677,9 +1618,8 @@
// If we don't have a comma, it is either the end of the list (a ';') or an
// error, bail out.
- while (Tok.is(tok::comma)) {
- SourceLocation CommaLoc = ConsumeToken();
-
+ SourceLocation CommaLoc;
+ while (TryConsumeToken(tok::comma, CommaLoc)) {
if (Tok.isAtStartOfLine() && ExpectSemi && !MightBeDeclarator(Context)) {
// This comma was followed by a line-break and something which can't be
// the start of a declarator. The comma was probably a typo for a
@@ -1724,8 +1664,7 @@
// Otherwise things are very confused and we skip to recover.
if (!isDeclarationSpecifier()) {
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
- if (Tok.is(tok::semi))
- ConsumeToken();
+ TryConsumeToken(tok::semi);
}
}
@@ -1975,8 +1914,7 @@
// Validate declspec for type-name.
unsigned Specs = DS.getParsedSpecifiers();
- if ((DSC == DSC_type_specifier || DSC == DSC_trailing) &&
- !DS.hasTypeSpecifier()) {
+ if (isTypeSpecifier(DSC) && !DS.hasTypeSpecifier()) {
Diag(Tok, diag::err_expected_type);
DS.SetTypeSpecError();
} else if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() &&
@@ -2074,8 +2012,7 @@
// within a type specifier. Outside of C++, we allow this even if the
// language doesn't "officially" support implicit int -- we support
// implicit int as an extension in C99 and C11.
- if (DSC != DSC_type_specifier && DSC != DSC_trailing &&
- !getLangOpts().CPlusPlus &&
+ if (!isTypeSpecifier(DSC) && !getLangOpts().CPlusPlus &&
isValidAfterIdentifierInDeclarator(NextToken())) {
// If this token is valid for implicit int, e.g. "static x = 4", then
// we just avoid eating the identifier, so it will be parsed as the
@@ -2145,7 +2082,7 @@
// Determine whether this identifier could plausibly be the name of something
// being declared (with a missing type).
- if (DSC != DSC_type_specifier && DSC != DSC_trailing &&
+ if (!isTypeSpecifier(DSC) &&
(!SS || DSC == DSC_top_level || DSC == DSC_class)) {
// Look ahead to the next token to try to figure out what this declaration
// was supposed to be.
@@ -2206,7 +2143,9 @@
// diagnostic and attempt to recover.
ParsedType T;
IdentifierInfo *II = Tok.getIdentifierInfo();
- if (Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T)) {
+ if (Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T,
+ getLangOpts().CPlusPlus &&
+ NextToken().is(tok::less))) {
// The action emitted a diagnostic, so we don't have to.
if (T) {
// The action has suggested that the type T could be used. Set that as
@@ -2214,7 +2153,8 @@
// name token, and we're done.
const char *PrevSpec;
unsigned DiagID;
- DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T);
+ DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
+ Actions.getASTContext().getPrintingPolicy());
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken();
// There may be other declaration specifiers after this.
@@ -2258,6 +2198,9 @@
return DSC_top_level;
if (Context == Declarator::TrailingReturnContext)
return DSC_trailing;
+ if (Context == Declarator::AliasDeclContext ||
+ Context == Declarator::AliasTemplateContext)
+ return DSC_alias_declaration;
return DSC_normal;
}
@@ -2282,8 +2225,8 @@
} else
ER = ParseConstantExpression();
- if (getLangOpts().CPlusPlus11 && Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
+ if (getLangOpts().CPlusPlus11)
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
return ER;
}
@@ -2305,7 +2248,7 @@
SourceLocation KWLoc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return;
SourceLocation EllipsisLoc;
@@ -2339,7 +2282,6 @@
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) ||
@@ -2349,63 +2291,77 @@
return true;
}
+ bool HasScope = Tok.is(tok::annot_cxxscope);
+ // Make a copy in case GetLookAheadToken invalidates the result of NextToken.
+ Token AfterScope = HasScope ? NextToken() : Tok;
+
// 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();
+ bool MightBeDeclarator = true;
+ if (Tok.is(tok::kw_typename) || Tok.is(tok::annot_typename)) {
+ // A declarator-id can't start with 'typename'.
+ MightBeDeclarator = false;
+ } else if (AfterScope.is(tok::annot_template_id)) {
+ // If we have a type expressed as a template-id, this cannot be a
+ // declarator-id (such a type cannot be redeclared in a simple-declaration).
+ TemplateIdAnnotation *Annot =
+ static_cast<TemplateIdAnnotation *>(AfterScope.getAnnotationValue());
+ if (Annot->Kind == TNK_Type_template)
+ MightBeDeclarator = false;
+ } else if (AfterScope.is(tok::identifier)) {
+ const Token &Next = HasScope ? GetLookAheadToken(2) : 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;
+ if (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)) {
+ // Missing a semicolon.
+ MightBeDeclarator = false;
+ } else if (HasScope) {
+ // If the declarator-id has a scope specifier, it must redeclare a
+ // previously-declared entity. If that's a type (and this is not a
+ // typedef), that's an error.
+ CXXScopeSpec SS;
+ Actions.RestoreNestedNameSpecifierAnnotation(
+ Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS);
+ IdentifierInfo *Name = AfterScope.getIdentifierInfo();
+ Sema::NameClassification Classification = Actions.ClassifyName(
+ getCurScope(), SS, Name, AfterScope.getLocation(), Next,
+ /*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_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_Type:
+ case Sema::NC_TypeTemplate:
+ // Not a previously-declared non-type entity.
+ MightBeDeclarator = false;
+ 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;
+ case Sema::NC_Unknown:
+ case Sema::NC_Expression:
+ case Sema::NC_VarTemplate:
+ case Sema::NC_FunctionTemplate:
+ // Might be a redeclaration of a prior entity.
+ break;
+ }
}
- } else if (Tok.is(tok::kw_typename) || Tok.is(tok::annot_typename)) {
- HasMissingSemi = true;
}
- if (!HasMissingSemi)
+ if (MightBeDeclarator)
return false;
+ const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getLocEnd()),
- diag::err_expected_semi_after_tagdecl)
- << DeclSpec::getSpecifierName(DS.getTypeSpecType());
+ diag::err_expected_after)
+ << DeclSpec::getSpecifierName(DS.getTypeSpecType(), PPol) << tok::semi;
// Try to recover from the typo, by dropping the tag definition and parsing
// the problematic tokens as a type.
@@ -2461,6 +2417,7 @@
bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
bool AttrsLastTime = false;
ParsedAttributesWithRange attrs(AttrFactory);
+ const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
while (1) {
bool isInvalid = false;
const char *PrevSpec = 0;
@@ -2484,7 +2441,7 @@
// If this is not a declaration specifier token, we're done reading decl
// specifiers. First verify that DeclSpec's are consistent.
- DS.Finish(Diags, PP);
+ DS.Finish(Diags, PP, Policy);
return;
case tok::l_square:
@@ -2586,7 +2543,7 @@
if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
TemplateId->Name &&
Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS)) {
- if (isConstructorDeclarator()) {
+ if (isConstructorDeclarator(/*Unqualified*/false)) {
// The user meant this to be an out-of-line constructor
// definition, but template arguments are not allowed
// there. Just allow this as a constructor; we'll
@@ -2618,7 +2575,7 @@
ParsedType T = getTypeAnnotation(Tok);
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename,
Tok.getAnnotationEndLoc(),
- PrevSpec, DiagID, T);
+ PrevSpec, DiagID, T, Policy);
if (isInvalid)
break;
}
@@ -2636,7 +2593,7 @@
if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(),
&SS)) {
- if (isConstructorDeclarator())
+ if (isConstructorDeclarator(/*Unqualified*/false))
goto DoneWithDeclSpec;
// As noted in C++ [class.qual]p2 (cited above), when the name
@@ -2677,7 +2634,7 @@
ConsumeToken(); // The C++ scope.
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
- DiagID, TypeRep);
+ DiagID, TypeRep, Policy);
if (isInvalid)
break;
@@ -2696,7 +2653,7 @@
if (Tok.getAnnotationValue()) {
ParsedType T = getTypeAnnotation(Tok);
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
- DiagID, T);
+ DiagID, T, Policy);
} else
DS.SetTypeSpecError();
@@ -2783,11 +2740,11 @@
// check whether this is a constructor declaration.
if (getLangOpts().CPlusPlus && DSContext == DSC_class &&
Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) &&
- isConstructorDeclarator())
+ isConstructorDeclarator(/*Unqualified*/true))
goto DoneWithDeclSpec;
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
- DiagID, TypeRep);
+ DiagID, TypeRep, Policy);
if (isInvalid)
break;
@@ -2819,7 +2776,7 @@
// constructor declaration.
if (getLangOpts().CPlusPlus && DSContext == DSC_class &&
Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) &&
- isConstructorDeclarator())
+ isConstructorDeclarator(TemplateId->SS.isEmpty()))
goto DoneWithDeclSpec;
// Turn the template-id annotation token into a type annotation
@@ -2843,10 +2800,8 @@
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, 0,
- AttributeList::AS_GNU);
+ AttributeList::AS_Keyword);
break;
}
@@ -2876,46 +2831,46 @@
// storage-class-specifier
case tok::kw_typedef:
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
case tok::kw_extern:
if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
Diag(Tok, diag::ext_thread_before) << "extern";
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
case tok::kw___private_extern__:
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern,
- Loc, PrevSpec, DiagID);
+ Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_static:
if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
Diag(Tok, diag::ext_thread_before) << "static";
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11) {
if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
if (!isInvalid)
Diag(Tok, diag::ext_auto_storage_class)
<< FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
} else
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
} else
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
case tok::kw_register:
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
case tok::kw_mutable:
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
case tok::kw___thread:
isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc,
@@ -2977,19 +2932,19 @@
// type-specifier
case tok::kw_short:
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_long:
if (DS.getTypeSpecWidth() != DeclSpec::TSW_long)
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
else
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw___int64:
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_signed:
isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec,
@@ -3009,43 +2964,43 @@
break;
case tok::kw_void:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_char:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_int:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw___int128:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_half:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_float:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_double:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_wchar_t:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_char16_t:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_char32_t:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw_bool:
case tok::kw__Bool:
@@ -3059,62 +3014,30 @@
isInvalid = true;
} else {
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
}
break;
case tok::kw__Decimal32:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw__Decimal64:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw__Decimal128:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,
- DiagID);
+ DiagID, Policy);
break;
case tok::kw___vector:
- isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw___pixel:
- isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
- break;
- case tok::kw_image1d_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image1d_array_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_array_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image1d_buffer_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_buffer_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image2d_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image2d_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image2d_array_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image2d_array_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image3d_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image3d_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_sampler_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_sampler_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_event_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_event_t, Loc,
- PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw___unknown_anytype:
isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
break;
// class-specifier:
@@ -3198,9 +3121,6 @@
break;
// OpenCL qualifiers:
- case tok::kw_private:
- if (!getLangOpts().OpenCL)
- goto DoneWithDeclSpec;
case tok::kw___private:
case tok::kw___global:
case tok::kw___local:
@@ -3208,7 +3128,7 @@
case tok::kw___read_only:
case tok::kw___write_only:
case tok::kw___read_write:
- ParseOpenCLQualifiers(DS);
+ ParseOpenCLQualifiers(DS.getAttributes());
break;
case tok::less:
@@ -3305,8 +3225,7 @@
ParseDeclarator(DeclaratorInfo.D);
}
- if (Tok.is(tok::colon)) {
- ConsumeToken();
+ if (TryConsumeToken(tok::colon)) {
ExprResult Res(ParseConstantExpression());
if (Res.isInvalid())
SkipUntil(tok::semi, StopBeforeMatch);
@@ -3322,12 +3241,9 @@
// If we don't have a comma, it is either the end of the list (a ';')
// or an error, bail out.
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma, CommaLoc))
return;
- // Consume the comma.
- CommaLoc = ConsumeToken();
-
FirstDeclarator = false;
}
}
@@ -3358,7 +3274,7 @@
SmallVector<Decl *, 32> FieldDecls;
// While we still have something to read, read the declarations in the struct.
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// Each iteration of this loop reads one struct-declaration.
// Check for extraneous top-level semicolon.
@@ -3394,7 +3310,7 @@
SmallVectorImpl<Decl *> &FieldDecls) :
P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {}
- void invoke(ParsingFieldDeclarator &FD) {
+ void invoke(ParsingFieldDeclarator &FD) override {
// Install the declarator into the current TagDecl.
Decl *Field = P.Actions.ActOnField(P.getCurScope(), TagDecl,
FD.D.getDeclSpec().getSourceRange().getBegin(),
@@ -3415,9 +3331,9 @@
continue;
}
ConsumeToken();
- ExpectAndConsume(tok::l_paren, diag::err_expected_lparen);
+ ExpectAndConsume(tok::l_paren);
if (!Tok.is(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::semi);
continue;
}
@@ -3426,21 +3342,22 @@
Tok.getIdentifierInfo(), Fields);
FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end());
ConsumeToken();
- ExpectAndConsume(tok::r_paren, diag::err_expected_rparen);
+ ExpectAndConsume(tok::r_paren);
}
- if (Tok.is(tok::semi)) {
- ConsumeToken();
- } else if (Tok.is(tok::r_brace)) {
+ if (TryConsumeToken(tok::semi))
+ continue;
+
+ if (Tok.is(tok::r_brace)) {
ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list);
break;
- } 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, StopAtSemi | StopBeforeMatch);
- // If we stopped at a ';', eat it.
- if (Tok.is(tok::semi)) ConsumeToken();
}
+
+ 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, StopAtSemi | StopBeforeMatch);
+ // If we stopped at a ';', eat it.
+ TryConsumeToken(tok::semi);
}
T.consumeClose();
@@ -3557,7 +3474,7 @@
return;
if (SS.isSet() && Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
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.
@@ -3570,7 +3487,7 @@
// Must have either 'enum name' or 'enum {...}'.
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) &&
!(AllowFixedUnderlyingType && Tok.is(tok::colon))) {
- Diag(Tok, diag::err_expected_ident_lbrace);
+ Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
// Skip the rest of this declarator, up until the comma or semicolon.
SkipUntil(tok::comma, StopAtSemi);
@@ -3696,15 +3613,14 @@
} else {
TUK = Sema::TUK_Definition;
}
- } else if (DSC != DSC_type_specifier &&
+ } else if (!isTypeSpecifier(DSC) &&
(Tok.is(tok::semi) ||
(Tok.isAtStartOfLine() &&
!isValidAfterTypeSpecifier(CanBeBitfield)))) {
TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
if (Tok.isNot(tok::semi)) {
// A semicolon was missing after this declaration. Diagnose and recover.
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
- "enum");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");
PP.EnterToken(Tok);
Tok.setKind(tok::semi);
}
@@ -3759,7 +3675,8 @@
StartLoc, SS, Name, NameLoc, attrs.getList(),
AS, DS.getModulePrivateSpecLoc(), TParams,
Owned, IsDependent, ScopedEnumKWLoc,
- IsScopedUsingClassTag, BaseType);
+ IsScopedUsingClassTag, BaseType,
+ DSC == DSC_type_specifier);
if (IsDependent) {
// This enum has a dependent nested-name-specifier. Handle it as a
@@ -3780,7 +3697,8 @@
if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc,
NameLoc.isValid() ? NameLoc : StartLoc,
- PrevSpec, DiagID, Type.get()))
+ PrevSpec, DiagID, Type.get(),
+ Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
return;
@@ -3803,7 +3721,8 @@
if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
NameLoc.isValid() ? NameLoc : StartLoc,
- PrevSpec, DiagID, TagDecl, Owned))
+ PrevSpec, DiagID, TagDecl, Owned,
+ Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
}
@@ -3834,7 +3753,16 @@
Decl *LastEnumConstDecl = 0;
// Parse the enumerator-list.
- while (Tok.is(tok::identifier)) {
+ while (Tok.isNot(tok::r_brace)) {
+ // Parse enumerator. If failed, try skipping till the start of the next
+ // enumerator definition.
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
+ if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch) &&
+ TryConsumeToken(tok::comma))
+ continue;
+ break;
+ }
IdentifierInfo *Ident = Tok.getIdentifierInfo();
SourceLocation IdentLoc = ConsumeToken();
@@ -3848,11 +3776,10 @@
ExprResult AssignedVal;
ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
+ if (TryConsumeToken(tok::equal, EqualLoc)) {
AssignedVal = ParseConstantExpression();
if (AssignedVal.isInvalid())
- SkipUntil(tok::comma, tok::r_brace, StopAtSemi | StopBeforeMatch);
+ SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch);
}
// Install the enumerator constant into EnumDecl.
@@ -3874,11 +3801,25 @@
continue;
}
- if (Tok.isNot(tok::comma))
- break;
- SourceLocation CommaLoc = ConsumeToken();
+ // Emumerator definition must be finished, only comma or r_brace are
+ // allowed here.
+ SourceLocation CommaLoc;
+ if (Tok.isNot(tok::r_brace) && !TryConsumeToken(tok::comma, CommaLoc)) {
+ if (EqualLoc.isValid())
+ Diag(Tok.getLocation(), diag::err_expected_either) << tok::r_brace
+ << tok::comma;
+ else
+ Diag(Tok.getLocation(), diag::err_expected_end_of_enumerator);
+ if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch)) {
+ if (TryConsumeToken(tok::comma, CommaLoc))
+ continue;
+ } else {
+ break;
+ }
+ }
- if (Tok.isNot(tok::identifier)) {
+ // If comma is followed by r_brace, emit appropriate warning.
+ if (Tok.is(tok::r_brace) && CommaLoc.isValid()) {
if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11)
Diag(CommaLoc, getLangOpts().CPlusPlus ?
diag::ext_enumerator_list_comma_cxx :
@@ -3887,6 +3828,7 @@
else if (getLangOpts().CPlusPlus11)
Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma)
<< FixItHint::CreateRemoval(CommaLoc);
+ break;
}
}
@@ -3910,7 +3852,7 @@
// was probably forgotten.
bool CanBeBitfield = getCurScope()->getFlags() & Scope::ClassScope;
if (!isValidAfterTypeSpecifier(CanBeBitfield)) {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, "enum");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");
// Push this token back into the preprocessor and change our current token
// to ';' so that the rest of the code recovers as though there were an
// ';' after the definition.
@@ -3924,12 +3866,7 @@
bool Parser::isTypeQualifier() const {
switch (Tok.getKind()) {
default: return false;
-
- // type-qualifier only in OpenCL
- case tok::kw_private:
- return getLangOpts().OpenCL;
-
- // type-qualifier
+ // type-qualifier
case tok::kw_const:
case tok::kw_volatile:
case tok::kw_restrict:
@@ -3975,16 +3912,6 @@
case tok::kw__Decimal128:
case tok::kw___vector:
- // OpenCL specific types:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t:
- case tok::kw_sampler_t:
- case tok::kw_event_t:
-
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
case tok::kw_struct:
@@ -4057,16 +3984,6 @@
case tok::kw__Decimal128:
case tok::kw___vector:
- // OpenCL specific types:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t:
- case tok::kw_sampler_t:
- case tok::kw_event_t:
-
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
case tok::kw_struct:
@@ -4111,9 +4028,6 @@
return true;
- case tok::kw_private:
- return getLangOpts().OpenCL;
-
// C11 _Atomic
case tok::kw__Atomic:
return true;
@@ -4129,9 +4043,6 @@
switch (Tok.getKind()) {
default: return false;
- case tok::kw_private:
- return getLangOpts().OpenCL;
-
case tok::identifier: // foo::bar
// Unfortunate hack to support "Class.factoryMethod" notation.
if (getLangOpts().ObjC1 && NextToken().is(tok::period))
@@ -4213,16 +4124,6 @@
case tok::kw__Decimal128:
case tok::kw___vector:
- // OpenCL specific types:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t:
- case tok::kw_sampler_t:
- case tok::kw_event_t:
-
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
case tok::kw_struct:
@@ -4300,7 +4201,7 @@
}
}
-bool Parser::isConstructorDeclarator() {
+bool Parser::isConstructorDeclarator(bool IsUnqualified) {
TentativeParsingAction TPA(*this);
// Parse the C++ scope specifier.
@@ -4382,12 +4283,35 @@
case tok::coloncolon:
// C(X :: Y);
// C(X :: *p);
- case tok::r_paren:
- // C(X )
// Assume this isn't a constructor, rather than assuming it's a
// constructor with an unnamed parameter of an ill-formed type.
break;
+ case tok::r_paren:
+ // C(X )
+ if (NextToken().is(tok::colon) || NextToken().is(tok::kw_try)) {
+ // Assume these were meant to be constructors:
+ // C(X) : (the name of a bit-field cannot be parenthesized).
+ // C(X) try (this is otherwise ill-formed).
+ IsConstructor = true;
+ }
+ if (NextToken().is(tok::semi) || NextToken().is(tok::l_brace)) {
+ // If we have a constructor name within the class definition,
+ // assume these were meant to be constructors:
+ // C(X) {
+ // C(X) ;
+ // ... because otherwise we would be declaring a non-static data
+ // member that is ill-formed because it's of the same type as its
+ // surrounding class.
+ //
+ // FIXME: We can actually do this whether or not the name is qualified,
+ // because if it is qualified in this context it must be being used as
+ // a constructor name. However, we do not implement that rule correctly
+ // currently, so we're somewhat conservative here.
+ IsConstructor = IsUnqualified;
+ }
+ break;
+
default:
IsConstructor = true;
break;
@@ -4455,9 +4379,6 @@
break;
// OpenCL qualifiers:
- case tok::kw_private:
- if (!getLangOpts().OpenCL)
- goto DoneWithTypeQuals;
case tok::kw___private:
case tok::kw___global:
case tok::kw___local:
@@ -4465,7 +4386,7 @@
case tok::kw___read_only:
case tok::kw___write_only:
case tok::kw___read_write:
- ParseOpenCLQualifiers(DS);
+ ParseOpenCLQualifiers(DS.getAttributes());
break;
case tok::kw___uptr:
@@ -4506,7 +4427,7 @@
DoneWithTypeQuals:
// If this is not a type-qualifier token, we're done reading type
// qualifiers. First verify that DeclSpec's are consistent.
- DS.Finish(Diags, PP);
+ DS.Finish(Diags, PP, Actions.getASTContext().getPrintingPolicy());
if (EndLoc.isValid())
DS.SetRangeEnd(EndLoc);
return;
@@ -4914,7 +4835,7 @@
<< getLangOpts().CPlusPlus;
}
} else
- Diag(Tok, diag::err_expected_ident_lparen);
+ Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_paren;
D.SetIdentifier(0, Tok.getLocation());
D.setInvalidType(true);
}
@@ -5122,7 +5043,6 @@
ParsedAttributes FnAttrs(AttrFactory);
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. */
@@ -5191,6 +5111,7 @@
// FIXME: currently, "static" case isn't handled correctly.
bool IsCXX11MemberFunction =
getLangOpts().CPlusPlus11 &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
(D.getContext() == Declarator::MemberContext
? !D.getDeclSpec().isFriendSpecified()
: D.getContext() == Declarator::FileContext &&
@@ -5250,8 +5171,6 @@
StartLoc, LocalEndLoc, D,
TrailingReturnType),
FnAttrs, EndLoc);
-
- Actions.ActOnEndFunctionDeclarator();
}
/// isFunctionDeclaratorIdentifierList - This parameter list may have an
@@ -5303,10 +5222,10 @@
// Maintain an efficient lookup of params we have seen so far.
llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
- while (1) {
+ do {
// If this isn't an identifier, report the error and skip until ')'.
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
// Forget we parsed anything.
ParamInfo.clear();
@@ -5331,12 +5250,8 @@
// Eat the identifier.
ConsumeToken();
-
// The list continues if we see a comma.
- if (Tok.isNot(tok::comma))
- break;
- ConsumeToken();
- }
+ } while (TryConsumeToken(tok::comma));
}
/// ParseParameterDeclarationClause - Parse a (possibly empty) parameter-list
@@ -5375,13 +5290,11 @@
ParsedAttributes &FirstArgAttrs,
SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
SourceLocation &EllipsisLoc) {
- while (1) {
- if (Tok.is(tok::ellipsis)) {
- // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
- // before deciding this was a parameter-declaration-clause.
- EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
+ do {
+ // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
+ // before deciding this was a parameter-declaration-clause.
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
break;
- }
// Parse the declaration-specifiers.
// Just use the ParsingDeclaration "scope" of the declarator.
@@ -5500,26 +5413,17 @@
Param, DefArgToks));
}
- // If the next token is a comma, consume it and keep reading arguments.
- if (Tok.isNot(tok::comma)) {
- if (Tok.is(tok::ellipsis)) {
- EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
-
- if (!getLangOpts().CPlusPlus) {
- // We have ellipsis without a preceding ',', which is ill-formed
- // in C. Complain and provide the fix.
- Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
- << FixItHint::CreateInsertion(EllipsisLoc, ", ");
- }
- }
-
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc) &&
+ !getLangOpts().CPlusPlus) {
+ // We have ellipsis without a preceding ',', which is ill-formed
+ // in C. Complain and provide the fix.
+ Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
+ << FixItHint::CreateInsertion(EllipsisLoc, ", ");
break;
}
- // Consume the comma.
- ConsumeToken();
- }
-
+ // If the next token is a comma, consume it and keep reading arguments.
+ } while (TryConsumeToken(tok::comma));
}
/// [C90] direct-declarator '[' constant-expression[opt] ']'
@@ -5544,7 +5448,6 @@
MaybeParseCXX11Attributes(attrs);
// Remember that we parsed the empty array type.
- ExprResult NumElements;
D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0,
T.getOpenLocation(),
T.getCloseLocation()),
@@ -5571,8 +5474,7 @@
// If valid, this location is the position where we read the 'static' keyword.
SourceLocation StaticLoc;
- if (Tok.is(tok::kw_static))
- StaticLoc = ConsumeToken();
+ TryConsumeToken(tok::kw_static, StaticLoc);
// If there is a type-qualifier-list, read it now.
// Type qualifiers in an array subscript are a C99 feature.
@@ -5581,8 +5483,8 @@
// If we haven't already read 'static', check to see if there is one after the
// type-qualifier-list.
- if (!StaticLoc.isValid() && Tok.is(tok::kw_static))
- StaticLoc = ConsumeToken();
+ if (!StaticLoc.isValid())
+ TryConsumeToken(tok::kw_static, StaticLoc);
// Handle "direct-declarator [ type-qual-list[opt] * ]".
bool isStar = false;
@@ -5678,7 +5580,8 @@
unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec,
- DiagID, CastTy))
+ DiagID, CastTy,
+ Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
return;
}
@@ -5700,7 +5603,8 @@
unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec,
- DiagID, Operand.get()))
+ DiagID, Operand.get(),
+ Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
}
@@ -5734,7 +5638,8 @@
const char *PrevSpec = 0;
unsigned DiagID;
if (DS.SetTypeSpecType(DeclSpec::TST_atomic, StartLoc, PrevSpec,
- DiagID, Result.release()))
+ DiagID, Result.release(),
+ Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
}
@@ -5774,6 +5679,7 @@
bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID,
bool &isInvalid) {
+ const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
if (Tok.getIdentifierInfo() == Ident_vector) {
Token Next = NextToken();
switch (Next.getKind()) {
@@ -5788,15 +5694,15 @@
case tok::kw_double:
case tok::kw_bool:
case tok::kw___pixel:
- isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
return true;
case tok::identifier:
if (Next.getIdentifierInfo() == Ident_pixel) {
- isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID,Policy);
return true;
}
if (Next.getIdentifierInfo() == Ident_bool) {
- isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID,Policy);
return true;
}
break;
@@ -5805,11 +5711,11 @@
}
} else if ((Tok.getIdentifierInfo() == Ident_pixel) &&
DS.isTypeAltiVecVector()) {
- isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy);
return true;
} else if ((Tok.getIdentifierInfo() == Ident_bool) &&
DS.isTypeAltiVecVector()) {
- isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID);
+ isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);
return true;
}
return false;
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index dd29f99..cef748f 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -13,9 +13,12 @@
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
-#include "clang/Basic/CharInfo.h"
-#include "clang/Basic/OperatorKinds.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/Attributes.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/OperatorKinds.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
@@ -91,7 +94,7 @@
if (Tok.is(tok::equal)) {
if (Ident == 0) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
// Skip to end of the definition and eat the ';'.
SkipUntil(tok::semi);
return 0;
@@ -111,8 +114,12 @@
Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon)
<< SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back());
}
- Diag(Tok, Ident ? diag::err_expected_lbrace :
- diag::err_expected_ident_lbrace);
+
+ if (Ident)
+ Diag(Tok, diag::err_expected) << tok::l_brace;
+ else
+ Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
+
return 0;
}
@@ -195,7 +202,7 @@
ParsedAttributes& attrs,
BalancedDelimiterTracker &Tracker) {
if (index == Ident.size()) {
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
MaybeParseMicrosoftAttributes(attrs);
@@ -259,8 +266,8 @@
// Eat the ';'.
DeclEnd = Tok.getLocation();
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name,
- "", tok::semi);
+ if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name))
+ SkipUntil(tok::semi);
return Actions.ActOnNamespaceAliasDef(getCurScope(), NamespaceLoc, AliasLoc, Alias,
SS, IdentLoc, Ident);
@@ -274,27 +281,16 @@
/// 'extern' string-literal declaration
///
Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
- assert(Tok.is(tok::string_literal) && "Not a string literal!");
- SmallString<8> LangBuffer;
- bool Invalid = false;
- StringRef Lang = PP.getSpelling(Tok, LangBuffer, &Invalid);
- if (Invalid)
- return 0;
-
- // FIXME: This is incorrect: linkage-specifiers are parsed in translation
- // phase 7, so string-literal concatenation is supposed to occur.
- // extern "" "C" "" "+" "+" { } is legal.
- if (Tok.hasUDSuffix())
- Diag(Tok, diag::err_invalid_string_udl);
- SourceLocation Loc = ConsumeStringToken();
+ assert(isTokenStringLiteral() && "Not a string literal!");
+ ExprResult Lang = ParseStringLiteralExpression(false);
ParseScope LinkageScope(this, Scope::DeclScope);
- Decl *LinkageSpec
- = Actions.ActOnStartLinkageSpecification(getCurScope(),
- DS.getSourceRange().getBegin(),
- Loc, Lang,
- Tok.is(tok::l_brace) ? Tok.getLocation()
- : SourceLocation());
+ Decl *LinkageSpec =
+ Lang.isInvalid()
+ ? 0
+ : Actions.ActOnStartLinkageSpecification(
+ getCurScope(), DS.getSourceRange().getBegin(), Lang.take(),
+ Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation());
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
@@ -308,8 +304,9 @@
// ... but anyway remember that such an "extern" was seen.
DS.setExternInLinkageSpec(true);
ParseExternalDeclaration(attrs, &DS);
- return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec,
- SourceLocation());
+ return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(
+ getCurScope(), LinkageSpec, SourceLocation())
+ : 0;
}
DS.abort();
@@ -318,16 +315,48 @@
BalancedDelimiterTracker T(*this, tok::l_brace);
T.consumeOpen();
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
- ParsedAttributesWithRange attrs(AttrFactory);
- MaybeParseCXX11Attributes(attrs);
- MaybeParseMicrosoftAttributes(attrs);
- ParseExternalDeclaration(attrs);
+
+ unsigned NestedModules = 0;
+ while (true) {
+ switch (Tok.getKind()) {
+ case tok::annot_module_begin:
+ ++NestedModules;
+ ParseTopLevelDecl();
+ continue;
+
+ case tok::annot_module_end:
+ if (!NestedModules)
+ break;
+ --NestedModules;
+ ParseTopLevelDecl();
+ continue;
+
+ case tok::annot_module_include:
+ ParseTopLevelDecl();
+ continue;
+
+ case tok::eof:
+ break;
+
+ case tok::r_brace:
+ if (!NestedModules)
+ break;
+ // Fall through.
+ default:
+ ParsedAttributesWithRange attrs(AttrFactory);
+ MaybeParseCXX11Attributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
+ ParseExternalDeclaration(attrs);
+ continue;
+ }
+
+ break;
}
T.consumeClose();
- return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec,
- T.getCloseLocation());
+ return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(
+ getCurScope(), LinkageSpec, T.getCloseLocation())
+ : 0;
}
/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
@@ -424,10 +453,10 @@
// Eat ';'.
DeclEnd = Tok.getLocation();
- ExpectAndConsume(tok::semi,
- GNUAttr ? diag::err_expected_semi_after_attribute_list
- : diag::err_expected_semi_after_namespace_name,
- "", tok::semi);
+ if (ExpectAndConsume(tok::semi,
+ GNUAttr ? diag::err_expected_semi_after_attribute_list
+ : diag::err_expected_semi_after_namespace_name))
+ SkipUntil(tok::semi);
return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS,
IdentLoc, NamespcName, attrs.getList());
@@ -461,10 +490,8 @@
// Ignore optional 'typename'.
// FIXME: This is wrong; we should parse this as a typename-specifier.
- if (Tok.is(tok::kw_typename)) {
- TypenameLoc = ConsumeToken();
+ if (TryConsumeToken(tok::kw_typename, TypenameLoc))
HasTypenameKeyword = true;
- }
// Parse nested-name-specifier.
IdentifierInfo *LastII = 0;
@@ -584,10 +611,11 @@
// Eat ';'.
DeclEnd = Tok.getLocation();
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- !Attrs.empty() ? "attributes list" :
- IsAliasDecl ? "alias declaration" : "using declaration",
- tok::semi);
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ !Attrs.empty() ? "attributes list"
+ : IsAliasDecl ? "alias declaration"
+ : "using declaration"))
+ SkipUntil(tok::semi);
// Diagnose an attempt to declare a templated using-declaration.
// In C++11, alias-declarations can be templates:
@@ -649,7 +677,7 @@
BalancedDelimiterTracker T(*this, tok::l_paren);
if (T.consumeOpen()) {
- Diag(Tok, diag::err_expected_lparen);
+ Diag(Tok, diag::err_expected) << tok::l_paren;
SkipMalformedDecl();
return 0;
}
@@ -660,8 +688,10 @@
return 0;
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::semi))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::semi);
return 0;
+ }
if (!isTokenStringLiteral()) {
Diag(Tok, diag::err_expected_string_literal)
@@ -781,12 +811,13 @@
const char *PrevSpec = 0;
unsigned DiagID;
+ const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
// Check for duplicate type specifiers (e.g. "int decltype(a)").
if (Result.get()
? DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec,
- DiagID, Result.release())
+ DiagID, Result.release(), Policy)
: DS.SetTypeSpecType(DeclSpec::TST_decltype_auto, StartLoc, PrevSpec,
- DiagID)) {
+ DiagID, Policy)) {
Diag(StartLoc, DiagID) << PrevSpec;
DS.SetTypeSpecError();
}
@@ -837,7 +868,8 @@
const char *PrevSpec = 0;
unsigned DiagID;
if (DS.SetTypeSpecType(DeclSpec::TST_underlyingType, StartLoc, PrevSpec,
- DiagID, Result.release()))
+ DiagID, Result.release(),
+ Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
DS.setTypeofParensRange(T.getRange());
}
@@ -985,7 +1017,8 @@
const char *PrevSpec = 0;
unsigned DiagID;
- DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type);
+ DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type,
+ Actions.getASTContext().getPrintingPolicy());
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
@@ -998,7 +1031,7 @@
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
- AttributeList::AS_GNU);
+ AttributeList::AS_Keyword);
}
}
@@ -1021,6 +1054,7 @@
case tok::l_paren: // struct foo {...} ( x);
case tok::comma: // __builtin_offsetof(struct foo{...} ,
case tok::kw_operator: // struct foo operator ++() {...}
+ case tok::kw___declspec: // struct foo {...} __declspec(...)
return true;
case tok::colon:
return CouldBeBitfield; // enum E { ... } : 2;
@@ -1179,31 +1213,17 @@
// C++11 attributes
SourceLocation AttrFixitLoc = Tok.getLocation();
- if (TagType == DeclSpec::TST_struct &&
- !Tok.is(tok::identifier) &&
- Tok.getIdentifierInfo() &&
- (Tok.is(tok::kw___is_arithmetic) ||
- Tok.is(tok::kw___is_convertible) ||
- Tok.is(tok::kw___is_empty) ||
- Tok.is(tok::kw___is_floating_point) ||
- Tok.is(tok::kw___is_function) ||
- Tok.is(tok::kw___is_fundamental) ||
- Tok.is(tok::kw___is_integral) ||
- Tok.is(tok::kw___is_member_function_pointer) ||
- Tok.is(tok::kw___is_member_pointer) ||
- Tok.is(tok::kw___is_pod) ||
- Tok.is(tok::kw___is_pointer) ||
- Tok.is(tok::kw___is_same) ||
- Tok.is(tok::kw___is_scalar) ||
- Tok.is(tok::kw___is_signed) ||
- Tok.is(tok::kw___is_unsigned) ||
- Tok.is(tok::kw___is_void)))
- // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the
- // name of struct templates, but some are keywords in GCC >= 4.3
- // and Clang. Therefore, when we see the token sequence "struct
- // X", make X into a normal identifier rather than a keyword, to
- // allow libstdc++ 4.2 and libc++ to work properly.
- TryKeywordIdentFallback(true);
+ // GNU libstdc++ and libc++ use certain intrinsic names as the
+ // name of struct templates, but some are keywords in GCC >= 4.3
+ // MSVC and Clang. For compatibility, convert the token to an identifier
+ // and issue a warning diagnostic.
+ if (TagType == DeclSpec::TST_struct && !Tok.is(tok::identifier) &&
+ !Tok.isAnnotation()) {
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ // We rarely end up here so the following check is efficient.
+ if (II && II->getName().startswith("__is_"))
+ TryKeywordIdentFallback(true);
+ }
// Parse the (optional) nested-name-specifier.
CXXScopeSpec &SS = DS.getTypeSpecScope();
@@ -1215,7 +1235,7 @@
DS.SetTypeSpecError();
if (SS.isSet())
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
}
TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
@@ -1243,13 +1263,8 @@
}
Diag(NameLoc, diag::err_explicit_spec_non_template)
- << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
- << (TagType == DeclSpec::TST_class? 0
- : TagType == DeclSpec::TST_struct? 1
- : TagType == DeclSpec::TST_union? 2
- : 3)
- << Name
- << SourceRange(LAngleLoc, RAngleLoc);
+ << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
+ << TagTokKind << Name << SourceRange(LAngleLoc, RAngleLoc);
// Strip off the last template parameter list if it was empty, since
// we've removed its template argument list.
@@ -1286,6 +1301,7 @@
if (SS.isNotEmpty())
Range.setBegin(SS.getBeginLoc());
+ // FIXME: Name may be null here.
Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)
<< TemplateId->Name << static_cast<int>(TemplateId->Kind) << Range;
@@ -1318,11 +1334,12 @@
// new struct s;
// or
// &T::operator struct s;
- // For these, DSC is DSC_type_specifier.
+ // For these, DSC is DSC_type_specifier or DSC_alias_declaration.
// If there are attributes after class name, parse them.
MaybeParseCXX11Attributes(Attributes);
+ const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
Sema::TagUseKind TUK;
if (DSC == DSC_trailing)
TUK = Sema::TUK_Reference;
@@ -1375,14 +1392,15 @@
TUK = Sema::TUK_Reference;
PA.Revert();
- } else if (DSC != DSC_type_specifier &&
+ } else if (!isTypeSpecifier(DSC) &&
(Tok.is(tok::semi) ||
(Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) {
TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
if (Tok.isNot(tok::semi)) {
+ const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
// A semicolon was missing after this declaration. Diagnose and recover.
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
- DeclSpec::getSpecifierName(TagType));
+ ExpectAndConsume(tok::semi, diag::err_expected_after,
+ DeclSpec::getSpecifierName(TagType, PPol));
PP.EnterToken(Tok);
Tok.setKind(tok::semi);
}
@@ -1424,7 +1442,7 @@
if (DS.getTypeSpecType() != DeclSpec::TST_error) {
// We have a declaration or reference to an anonymous class.
Diag(StartLoc, diag::err_anon_type_definition)
- << DeclSpec::getSpecifierName(TagType);
+ << DeclSpec::getSpecifierName(TagType, Policy);
}
// If we are parsing a definition and stop at a base-clause, continue on
@@ -1591,7 +1609,8 @@
DS.getModulePrivateSpecLoc(),
TParams, Owned, IsDependent,
SourceLocation(), false,
- clang::TypeResult());
+ clang::TypeResult(),
+ DSC == DSC_type_specifier);
// If ActOnTag said the type was dependent, try again with the
// less common call.
@@ -1620,11 +1639,12 @@
if (!TypeResult.isInvalid()) {
Result = DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc,
NameLoc.isValid() ? NameLoc : StartLoc,
- PrevSpec, DiagID, TypeResult.get());
+ PrevSpec, DiagID, TypeResult.get(), Policy);
} else if (!TagOrTempResult.isInvalid()) {
Result = DS.SetTypeSpecType(TagType, StartLoc,
NameLoc.isValid() ? NameLoc : StartLoc,
- PrevSpec, DiagID, TagOrTempResult.get(), Owned);
+ PrevSpec, DiagID, TagOrTempResult.get(), Owned,
+ Policy);
} else {
DS.SetTypeSpecError();
return;
@@ -1645,8 +1665,9 @@
if (TUK == Sema::TUK_Definition &&
(TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {
if (Tok.isNot(tok::semi)) {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
- DeclSpec::getSpecifierName(TagType));
+ const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
+ ExpectAndConsume(tok::semi, diag::err_expected_after,
+ DeclSpec::getSpecifierName(TagType, PPol));
// Push this token back into the preprocessor and change our current token
// to ';' so that the rest of the code recovers as though there were an
// ';' after the definition.
@@ -1684,10 +1705,8 @@
// If the next token is a comma, consume it and keep reading
// base-specifiers.
- if (Tok.isNot(tok::comma)) break;
-
- // Consume the comma.
- ConsumeToken();
+ if (!TryConsumeToken(tok::comma))
+ break;
}
// Attach the base specifiers
@@ -1713,10 +1732,8 @@
MaybeParseCXX11Attributes(Attributes);
// Parse the 'virtual' keyword.
- if (Tok.is(tok::kw_virtual)) {
- ConsumeToken();
+ if (TryConsumeToken(tok::kw_virtual))
IsVirtual = true;
- }
CheckMisplacedCXX11Attribute(Attributes, StartLoc);
@@ -1753,9 +1770,8 @@
// actually part of the base-specifier-list grammar productions, but we
// parse it here for convenience.
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
-
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
+
// Find the complete source range for the base-specifier.
SourceRange Range(StartLoc, EndLocation);
@@ -1793,8 +1809,8 @@
DeclaratorChunk::FunctionTypeInfo &FTI
= DeclaratorInfo.getFunctionTypeInfo();
- for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) {
- if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) {
+ for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) {
+ if (LateMethod || FTI.Params[ParamIdx].DefaultArgTokens) {
if (!LateMethod) {
// Push this method onto the stack of late-parsed method
// declarations.
@@ -1804,17 +1820,16 @@
// Add all of the parameters prior to this one (they don't
// have default arguments).
- LateMethod->DefaultArgs.reserve(FTI.NumArgs);
+ LateMethod->DefaultArgs.reserve(FTI.NumParams);
for (unsigned I = 0; I < ParamIdx; ++I)
LateMethod->DefaultArgs.push_back(
- LateParsedDefaultArgument(FTI.ArgInfo[I].Param));
+ LateParsedDefaultArgument(FTI.Params[I].Param));
}
// Add this parameter to the list of parameters (it may or may
// not have a default argument).
- LateMethod->DefaultArgs.push_back(
- LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param,
- FTI.ArgInfo[ParamIdx].DefaultArgTokens));
+ LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument(
+ FTI.Params[ParamIdx].Param, FTI.Params[ParamIdx].DefaultArgTokens));
}
}
}
@@ -1826,30 +1841,28 @@
/// override
/// final
VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const {
- if (!getLangOpts().CPlusPlus)
+ if (!getLangOpts().CPlusPlus || Tok.isNot(tok::identifier))
return VirtSpecifiers::VS_None;
- if (Tok.is(tok::identifier)) {
- IdentifierInfo *II = Tok.getIdentifierInfo();
+ IdentifierInfo *II = Tok.getIdentifierInfo();
- // Initialize the contextual keywords.
- if (!Ident_final) {
- Ident_final = &PP.getIdentifierTable().get("final");
- if (getLangOpts().MicrosoftExt)
- Ident_sealed = &PP.getIdentifierTable().get("sealed");
- Ident_override = &PP.getIdentifierTable().get("override");
- }
-
- if (II == Ident_override)
- return VirtSpecifiers::VS_Override;
-
- if (II == Ident_sealed)
- return VirtSpecifiers::VS_Sealed;
-
- if (II == Ident_final)
- return VirtSpecifiers::VS_Final;
+ // Initialize the contextual keywords.
+ if (!Ident_final) {
+ Ident_final = &PP.getIdentifierTable().get("final");
+ if (getLangOpts().MicrosoftExt)
+ Ident_sealed = &PP.getIdentifierTable().get("sealed");
+ Ident_override = &PP.getIdentifierTable().get("override");
}
+ if (II == Ident_override)
+ return VirtSpecifiers::VS_Override;
+
+ if (II == Ident_sealed)
+ return VirtSpecifiers::VS_Sealed;
+
+ if (II == Ident_final)
+ return VirtSpecifiers::VS_Final;
+
return VirtSpecifiers::VS_None;
}
@@ -1891,24 +1904,58 @@
}
/// isCXX11FinalKeyword - Determine whether the next token is a C++11
-/// contextual 'final' keyword.
+/// 'final' or Microsoft 'sealed' contextual keyword.
bool Parser::isCXX11FinalKeyword() const {
- if (!getLangOpts().CPlusPlus)
- return false;
+ VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();
+ return Specifier == VirtSpecifiers::VS_Final ||
+ Specifier == VirtSpecifiers::VS_Sealed;
+}
- if (!Tok.is(tok::identifier))
- return false;
-
- // Initialize the contextual keywords.
- if (!Ident_final) {
- Ident_final = &PP.getIdentifierTable().get("final");
- if (getLangOpts().MicrosoftExt)
- Ident_sealed = &PP.getIdentifierTable().get("sealed");
- Ident_override = &PP.getIdentifierTable().get("override");
+/// \brief Parse a C++ member-declarator up to, but not including, the optional
+/// brace-or-equal-initializer or pure-specifier.
+void Parser::ParseCXXMemberDeclaratorBeforeInitializer(
+ Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize,
+ LateParsedAttrList &LateParsedAttrs) {
+ // member-declarator:
+ // declarator pure-specifier[opt]
+ // declarator brace-or-equal-initializer[opt]
+ // identifier[opt] ':' constant-expression
+ if (Tok.isNot(tok::colon)) {
+ // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
+ // is a bitfield.
+ // FIXME: This should only apply when parsing the id-expression (see
+ // PR18587).
+ ColonProtectionRAIIObject X(*this);
+ ParseDeclarator(DeclaratorInfo);
}
- return Tok.getIdentifierInfo() == Ident_final ||
- Tok.getIdentifierInfo() == Ident_sealed;
+ if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) {
+ BitfieldSize = ParseConstantExpression();
+ if (BitfieldSize.isInvalid())
+ SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
+ } else
+ ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface);
+
+ // If a simple-asm-expr is present, parse it.
+ if (Tok.is(tok::kw_asm)) {
+ SourceLocation Loc;
+ ExprResult AsmLabel(ParseSimpleAsm(&Loc));
+ if (AsmLabel.isInvalid())
+ SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
+
+ DeclaratorInfo.setAsmLabel(AsmLabel.release());
+ DeclaratorInfo.SetRangeEnd(Loc);
+ }
+
+ // If attributes exist after the declarator, but before an '{', parse them.
+ MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);
+
+ // For compatibility with code written to older Clang, also accept a
+ // virt-specifier *after* the GNU attributes.
+ // FIXME: If we saw any attributes that are known to GCC followed by a
+ // virt-specifier, issue a GCC-compat warning.
+ if (BitfieldSize.isUnset() && VS.isUnset())
+ ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface);
}
/// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
@@ -1993,11 +2040,11 @@
}
// TODO: recover from mistakenly-qualified operator declarations.
- if (ExpectAndConsume(tok::semi,
- diag::err_expected_semi_after,
- "access declaration",
- tok::semi))
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ "access declaration")) {
+ SkipUntil(tok::semi);
return;
+ }
Actions.ActOnUsingDeclaration(getCurScope(), AS,
/* HasUsingKeyword */ false,
@@ -2036,10 +2083,6 @@
TemplateInfo, TemplateDiags);
}
- // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
- // is a bitfield.
- ColonProtectionRAIIObject X(*this);
-
ParsedAttributesWithRange attrs(AttrFactory);
ParsedAttributesWithRange FnAttrs(AttrFactory);
// Optional C++11 attribute-specifier
@@ -2078,8 +2121,14 @@
DS.takeAttributesFrom(attrs);
if (MalformedTypeSpec)
DS.SetTypeSpecError();
- ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
- &CommonLateParsedAttrs);
+
+ {
+ // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
+ // is a bitfield.
+ ColonProtectionRAIIObject X(*this);
+ ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
+ &CommonLateParsedAttrs);
+ }
// If we had a free-standing type definition with a missing semicolon, we
// may get this far before the problem becomes obvious.
@@ -2093,9 +2142,7 @@
TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
- if (Tok.is(tok::semi)) {
- ConsumeToken();
-
+ if (TryConsumeToken(tok::semi)) {
if (DS.isFriendSpecified())
ProhibitAttributes(FnAttrs);
@@ -2114,30 +2161,30 @@
SourceLocation EqualLoc;
bool HasInitializer = false;
ExprResult Init;
- if (Tok.isNot(tok::colon)) {
- // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
- ColonProtectionRAIIObject X(*this);
- // Parse the first declarator.
- ParseDeclarator(DeclaratorInfo);
- // Error parsing the declarator?
- if (!DeclaratorInfo.hasName()) {
- // If so, skip until the semi-colon or a }.
- SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
- if (Tok.is(tok::semi))
- ConsumeToken();
- return;
- }
+ SmallVector<Decl *, 8> DeclsInGroup;
+ ExprResult BitfieldSize;
+ bool ExpectSemi = true;
- ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface);
+ // Parse the first declarator.
+ ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize,
+ LateParsedAttrs);
- // If attributes exist after the declarator, but before an '{', parse them.
- MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);
+ // If this has neither a name nor a bit width, something has gone seriously
+ // wrong. Skip until the semi-colon or }.
+ if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) {
+ // If so, skip until the semi-colon or a }.
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
+ TryConsumeToken(tok::semi);
+ return;
+ }
- // MSVC permits pure specifier on inline functions declared at class scope.
+ // Check for a member function definition.
+ if (BitfieldSize.isUnset()) {
+ // MSVC permits pure specifier on inline functions defined at class scope.
// Hence check for =0 before checking for function definition.
if (getLangOpts().MicrosoftExt && Tok.is(tok::equal) &&
- DeclaratorInfo.isFunctionDeclarator() &&
+ DeclaratorInfo.isFunctionDeclarator() &&
NextToken().is(tok::numeric_constant)) {
EqualLoc = ConsumeToken();
Init = ParseInitializer();
@@ -2183,8 +2230,8 @@
SkipUntil(tok::r_brace);
// Consume the optional ';'
- if (Tok.is(tok::semi))
- ConsumeToken();
+ TryConsumeToken(tok::semi);
+
return;
}
@@ -2222,40 +2269,7 @@
// member-declarator
// member-declarator-list ',' member-declarator
- SmallVector<Decl *, 8> DeclsInGroup;
- ExprResult BitfieldSize;
- bool ExpectSemi = true;
-
while (1) {
- // member-declarator:
- // declarator pure-specifier[opt]
- // declarator brace-or-equal-initializer[opt]
- // identifier[opt] ':' constant-expression
- if (Tok.is(tok::colon)) {
- ConsumeToken();
- BitfieldSize = ParseConstantExpression();
- if (BitfieldSize.isInvalid())
- SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
- }
-
- // If a simple-asm-expr is present, parse it.
- if (Tok.is(tok::kw_asm)) {
- SourceLocation Loc;
- ExprResult AsmLabel(ParseSimpleAsm(&Loc));
- if (AsmLabel.isInvalid())
- SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
-
- DeclaratorInfo.setAsmLabel(AsmLabel.release());
- DeclaratorInfo.SetRangeEnd(Loc);
- }
-
- // If attributes exist after the declarator, parse them.
- MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);
-
- // FIXME: When g++ adds support for this, we'll need to check whether it
- // goes before or after the GNU attributes and __asm__.
- ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface);
-
InClassInitStyle HasInClassInit = ICIS_NoInit;
if ((Tok.is(tok::equal) || Tok.is(tok::l_brace)) && !HasInitializer) {
if (BitfieldSize.get()) {
@@ -2276,22 +2290,18 @@
NamedDecl *ThisDecl = 0;
if (DS.isFriendSpecified()) {
- // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
+ // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
// to a friend declaration, that declaration shall be a definition.
//
- // Diagnose attributes appear after friend member function declarator:
- // foo [[]] ();
+ // Diagnose attributes that appear in a friend member function declarator:
+ // friend int foo [[]] ();
SmallVector<SourceRange, 4> Ranges;
DeclaratorInfo.getCXX11AttributeRanges(Ranges);
- if (!Ranges.empty()) {
- for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(),
- E = Ranges.end(); I != E; ++I) {
- Diag((*I).getBegin(), diag::err_attributes_not_allowed)
- << *I;
- }
- }
+ for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(),
+ E = Ranges.end(); I != E; ++I)
+ Diag((*I).getBegin(), diag::err_attributes_not_allowed) << *I;
- // TODO: handle initializers, bitfields, 'delete'
+ // TODO: handle initializers, VS, bitfields, 'delete'
ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,
TemplateParams);
} else {
@@ -2372,12 +2382,10 @@
// If we don't have a comma, it is either the end of the list (a ';')
// or an error, bail out.
- if (Tok.isNot(tok::comma))
+ SourceLocation CommaLoc;
+ if (!TryConsumeToken(tok::comma, CommaLoc))
break;
- // Consume the comma.
- SourceLocation CommaLoc = ConsumeToken();
-
if (Tok.isAtStartOfLine() &&
!MightBeDeclarator(Declarator::MemberContext)) {
// This comma was followed by a line-break and something which can't be
@@ -2397,11 +2405,11 @@
HasInitializer = false;
DeclaratorInfo.setCommaLoc(CommaLoc);
- // Attributes are only allowed on the second declarator.
+ // GNU attributes are allowed before the second and subsequent declarator.
MaybeParseGNUAttributes(DeclaratorInfo);
- if (Tok.isNot(tok::colon))
- ParseDeclarator(DeclaratorInfo);
+ ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize,
+ LateParsedAttrs);
}
if (ExpectSemi &&
@@ -2409,7 +2417,7 @@
// Skip to end of block or statement.
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
// If we stopped at a ';', eat it.
- if (Tok.is(tok::semi)) ConsumeToken();
+ TryConsumeToken(tok::semi);
return;
}
@@ -2446,8 +2454,7 @@
EnterExpressionEvaluationContext Context(Actions,
Sema::PotentiallyEvaluated,
D);
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
+ if (TryConsumeToken(tok::equal, EqualLoc)) {
if (Tok.is(tok::kw_delete)) {
// In principle, an initializer of '= delete p;' is legal, but it will
// never type-check. It's better to diagnose it as an ill-formed expression
@@ -2456,7 +2463,7 @@
// a top-level comma always ends the initializer expression.
const Token &Next = NextToken();
if (IsFunction || Next.is(tok::semi) || Next.is(tok::comma) ||
- Next.is(tok::eof)) {
+ Next.is(tok::eof)) {
if (IsFunction)
Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
<< 1 /* delete */;
@@ -2510,7 +2517,7 @@
<< /*ErrorType=*/6
<< (isa<NamedDecl>(TagDecl)
? cast<NamedDecl>(TagDecl)->getQualifiedNameAsString()
- : "<anonymous>");
+ : "(anonymous)");
}
break;
}
@@ -2601,7 +2608,7 @@
if (TagDecl) {
// While we still have something to read, read the member-declarations.
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// Each iteration of this loop reads one member-declaration.
if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
@@ -2636,6 +2643,11 @@
continue;
}
+ if (Tok.is(tok::annot_pragma_ms_pointers_to_members)) {
+ HandlePragmaMSPointersToMembers();
+ continue;
+ }
+
// If we see a namespace here, a close brace was missing somewhere.
if (Tok.is(tok::kw_namespace)) {
DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl));
@@ -2653,18 +2665,14 @@
MaybeParseGNUAttributes(AccessAttrs);
SourceLocation EndLoc;
- if (Tok.is(tok::colon)) {
- EndLoc = Tok.getLocation();
- ConsumeToken();
- } else if (Tok.is(tok::semi)) {
- EndLoc = Tok.getLocation();
- ConsumeToken();
- Diag(EndLoc, diag::err_expected_colon)
- << FixItHint::CreateReplacement(EndLoc, ":");
+ if (TryConsumeToken(tok::colon, EndLoc)) {
+ } else if (TryConsumeToken(tok::semi, EndLoc)) {
+ Diag(EndLoc, diag::err_expected)
+ << tok::colon << FixItHint::CreateReplacement(EndLoc, ":");
} else {
EndLoc = ASLoc.getLocWithOffset(TokLength);
- Diag(EndLoc, diag::err_expected_colon)
- << FixItHint::CreateInsertion(EndLoc, ":");
+ Diag(EndLoc, diag::err_expected)
+ << tok::colon << FixItHint::CreateInsertion(EndLoc, ":");
}
// The Microsoft extension __interface does not permit non-public
@@ -2810,7 +2818,8 @@
<< FixItHint::CreateInsertion(Loc, ", ");
} else {
// Skip over garbage, until we get to '{'. Don't eat the '{'.
- Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
+ Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace
+ << tok::comma;
SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
break;
}
@@ -2878,8 +2887,7 @@
return true;
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
TemplateTypeTy, DS, IdLoc,
@@ -2899,8 +2907,7 @@
T.consumeClose();
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
TemplateTypeTy, DS, IdLoc,
@@ -2908,9 +2915,10 @@
T.getCloseLocation(), EllipsisLoc);
}
- Diag(Tok, getLangOpts().CPlusPlus11 ? diag::err_expected_lparen_or_lbrace
- : diag::err_expected_lparen);
- return true;
+ if (getLangOpts().CPlusPlus11)
+ return Diag(Tok, diag::err_expected_either) << tok::l_paren << tok::l_brace;
+ else
+ return Diag(Tok, diag::err_expected) << tok::l_paren;
}
/// \brief Parse a C++ exception-specification if present (C++0x [except.spec]).
@@ -3054,10 +3062,8 @@
Exceptions.push_back(Res.get());
Ranges.push_back(Range);
}
-
- if (Tok.is(tok::comma))
- ConsumeToken();
- else
+
+ if (!TryConsumeToken(tok::comma))
break;
}
@@ -3193,8 +3199,50 @@
}
}
-/// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier. Currently
-/// only parses standard attributes.
+/// ParseCXX11AttributeArgs -- Parse a C++11 attribute-argument-clause.
+///
+/// [C++11] attribute-argument-clause:
+/// '(' balanced-token-seq ')'
+///
+/// [C++11] balanced-token-seq:
+/// balanced-token
+/// balanced-token-seq balanced-token
+///
+/// [C++11] balanced-token:
+/// '(' balanced-token-seq ')'
+/// '[' balanced-token-seq ']'
+/// '{' balanced-token-seq '}'
+/// any token but '(', ')', '[', ']', '{', or '}'
+bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs,
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc) {
+ assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");
+
+ // If the attribute isn't known, we will not attempt to parse any
+ // arguments.
+ if (!hasAttribute(AttrSyntax::CXX, ScopeName, AttrName,
+ getTargetInfo().getTriple(), getLangOpts())) {
+ // Eat the left paren, then skip to the ending right paren.
+ ConsumeParen();
+ SkipUntil(tok::r_paren);
+ return false;
+ }
+
+ if (ScopeName && ScopeName->getName() == "gnu")
+ // GNU-scoped attributes have some special cases to handle GNU-specific
+ // behaviors.
+ ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
+ ScopeLoc, AttributeList::AS_CXX11, 0);
+ else
+ ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
+ ScopeLoc, AttributeList::AS_CXX11);
+ return true;
+}
+
+/// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier.
///
/// [C++11] attribute-specifier:
/// '[' '[' attribute-list ']' ']'
@@ -3218,19 +3266,6 @@
///
/// [C++11] attribute-namespace:
/// identifier
-///
-/// [C++11] attribute-argument-clause:
-/// '(' balanced-token-seq ')'
-///
-/// [C++11] balanced-token-seq:
-/// balanced-token
-/// balanced-token-seq balanced-token
-///
-/// [C++11] balanced-token:
-/// '(' balanced-token-seq ')'
-/// '[' balanced-token-seq ']'
-/// '{' balanced-token-seq '}'
-/// any token but '(', ')', '[', ']', '{', or '}'
void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
SourceLocation *endLoc) {
if (Tok.is(tok::kw_alignas)) {
@@ -3251,10 +3286,8 @@
while (Tok.isNot(tok::r_square)) {
// attribute not present
- if (Tok.is(tok::comma)) {
- ConsumeToken();
+ if (TryConsumeToken(tok::comma))
continue;
- }
SourceLocation ScopeLoc, AttrLoc;
IdentifierInfo *ScopeName = 0, *AttrName = 0;
@@ -3265,43 +3298,34 @@
break;
// scoped attribute
- if (Tok.is(tok::coloncolon)) {
- ConsumeToken();
-
+ if (TryConsumeToken(tok::coloncolon)) {
ScopeName = AttrName;
ScopeLoc = AttrLoc;
AttrName = TryParseCXX11AttributeIdentifier(AttrLoc);
if (!AttrName) {
- Diag(Tok.getLocation(), diag::err_expected_ident);
+ Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch);
continue;
}
}
- bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName,ScopeName);
+ bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName);
bool AttrParsed = false;
if (StandardAttr &&
!SeenAttrs.insert(std::make_pair(AttrName, AttrLoc)).second)
Diag(AttrLoc, diag::err_cxx11_attribute_repeated)
- << AttrName << SourceRange(SeenAttrs[AttrName]);
+ << AttrName << SourceRange(SeenAttrs[AttrName]);
// Parse attribute arguments
if (Tok.is(tok::l_paren)) {
- if (ScopeName && ScopeName->getName() == "gnu") {
- ParseGNUAttributeArgs(AttrName, AttrLoc, attrs, endLoc,
- ScopeName, ScopeLoc, AttributeList::AS_CXX11);
- AttrParsed = true;
- } else {
- if (StandardAttr)
- Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments)
+ if (StandardAttr)
+ Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments)
<< AttrName->getName();
- // FIXME: handle other formats of c++11 attribute arguments
- ConsumeParen();
- SkipUntil(tok::r_paren);
- }
+ AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, attrs, endLoc,
+ ScopeName, ScopeLoc);
}
if (!AttrParsed)
@@ -3310,19 +3334,16 @@
AttrLoc),
ScopeName, ScopeLoc, 0, 0, AttributeList::AS_CXX11);
- if (Tok.is(tok::ellipsis)) {
- ConsumeToken();
-
+ if (TryConsumeToken(tok::ellipsis))
Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
<< AttrName->getName();
- }
}
- if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+ if (ExpectAndConsume(tok::r_square))
SkipUntil(tok::r_square);
if (endLoc)
*endLoc = Tok.getLocation();
- if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+ if (ExpectAndConsume(tok::r_square))
SkipUntil(tok::r_square);
}
@@ -3393,7 +3414,7 @@
ConsumeBracket();
SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch);
if (endLoc) *endLoc = Tok.getLocation();
- ExpectAndConsume(tok::r_square, diag::err_expected_rsquare);
+ ExpectAndConsume(tok::r_square);
}
}
@@ -3405,7 +3426,7 @@
BalancedDelimiterTracker Braces(*this, tok::l_brace);
if (Braces.consumeOpen()) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return;
}
@@ -3424,7 +3445,7 @@
return;
}
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// __if_exists, __if_not_exists can nest.
if ((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) {
ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);
@@ -3446,7 +3467,7 @@
if (Tok.is(tok::colon))
Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation());
else
- Diag(Tok, diag::err_expected_colon);
+ Diag(Tok, diag::err_expected) << tok::colon;
ConsumeToken();
continue;
}
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 45f1b1d..ed9d72d 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -23,6 +23,7 @@
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
+#include "clang/AST/ASTContext.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
@@ -269,10 +270,7 @@
Diag(Tok, diag::ext_gnu_conditional_expr);
}
- if (Tok.is(tok::colon)) {
- // Eat the colon.
- ColonLoc = ConsumeToken();
- } else {
+ if (!TryConsumeToken(tok::colon, ColonLoc)) {
// Otherwise, we're missing a ':'. Assume that this was a typo that
// the user forgot. If we're not in a macro expansion, we can suggest
// a fixit hint. If there were two spaces before the current token,
@@ -294,10 +292,10 @@
}
}
}
-
- Diag(Tok, diag::err_expected_colon)
- << FixItHint::CreateInsertion(FILoc, FIText);
- Diag(OpToken, diag::note_matching) << "?";
+
+ Diag(Tok, diag::err_expected)
+ << tok::colon << FixItHint::CreateInsertion(FILoc, FIText);
+ Diag(OpToken, diag::note_matching) << tok::question;
ColonLoc = Tok.getLocation();
}
}
@@ -430,7 +428,7 @@
WantTypeSpecifiers = AllowTypes;
}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
NamedDecl *ND = candidate.getCorrectionDecl();
if (!ND)
return candidate.isKeyword();
@@ -715,48 +713,11 @@
// If this identifier was reverted from a token ID, and the next token
// is a parenthesis, this is likely to be a use of a type trait. Check
// those tokens.
- if (Next.is(tok::l_paren) &&
- Tok.is(tok::identifier) &&
- Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier()) {
- IdentifierInfo *II = Tok.getIdentifierInfo();
- // Build up the mapping of revertable type traits, for future use.
- if (RevertableTypeTraits.empty()) {
-#define RTT_JOIN(X,Y) X##Y
-#define REVERTABLE_TYPE_TRAIT(Name) \
- RevertableTypeTraits[PP.getIdentifierInfo(#Name)] \
- = RTT_JOIN(tok::kw_,Name)
-
- REVERTABLE_TYPE_TRAIT(__is_arithmetic);
- REVERTABLE_TYPE_TRAIT(__is_convertible);
- REVERTABLE_TYPE_TRAIT(__is_empty);
- REVERTABLE_TYPE_TRAIT(__is_floating_point);
- REVERTABLE_TYPE_TRAIT(__is_function);
- REVERTABLE_TYPE_TRAIT(__is_fundamental);
- REVERTABLE_TYPE_TRAIT(__is_integral);
- REVERTABLE_TYPE_TRAIT(__is_member_function_pointer);
- REVERTABLE_TYPE_TRAIT(__is_member_pointer);
- REVERTABLE_TYPE_TRAIT(__is_pod);
- REVERTABLE_TYPE_TRAIT(__is_pointer);
- REVERTABLE_TYPE_TRAIT(__is_same);
- REVERTABLE_TYPE_TRAIT(__is_scalar);
- REVERTABLE_TYPE_TRAIT(__is_signed);
- REVERTABLE_TYPE_TRAIT(__is_unsigned);
- REVERTABLE_TYPE_TRAIT(__is_void);
-#undef REVERTABLE_TYPE_TRAIT
-#undef RTT_JOIN
- }
-
- // If we find that this is in fact the name of a type trait,
- // update the token kind in place and parse again to treat it as
- // the appropriate kind of type trait.
- llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind>::iterator Known
- = RevertableTypeTraits.find(II);
- if (Known != RevertableTypeTraits.end()) {
- Tok.setKind(Known->second);
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, isTypeCast);
- }
- }
+ if (Next.is(tok::l_paren) && Tok.is(tok::identifier) &&
+ Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier() &&
+ TryIdentKeywordUpgrade())
+ return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
+ NotCastExpr, isTypeCast);
if (Next.is(tok::coloncolon) ||
(!ColonIsSacred && Next.is(tok::colon)) ||
@@ -830,7 +791,8 @@
DS.SetRangeEnd(ILoc);
const char *PrevSpec = 0;
unsigned DiagID;
- DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ);
+ DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ,
+ Actions.getASTContext().getPrintingPolicy());
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
TypeResult Ty = Actions.ActOnTypeName(getCurScope(),
@@ -955,7 +917,7 @@
case tok::ampamp: { // unary-expression: '&&' identifier
SourceLocation AmpAmpLoc = ConsumeToken();
if (Tok.isNot(tok::identifier))
- return ExprError(Diag(Tok, diag::err_expected_ident));
+ return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
if (getCurScope()->getFnParent() == 0)
return ExprError(Diag(Tok, diag::err_address_of_label_outside_fn));
@@ -995,7 +957,8 @@
const char *PrevSpec = 0;
unsigned DiagID;
DS.SetTypeSpecType(TST_typename, Tok.getAnnotationEndLoc(),
- PrevSpec, DiagID, Type);
+ PrevSpec, DiagID, Type,
+ Actions.getASTContext().getPrintingPolicy());
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
@@ -1028,15 +991,7 @@
case tok::kw_void:
case tok::kw_typename:
case tok::kw_typeof:
- case tok::kw___vector:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t:
- case tok::kw_sampler_t:
- case tok::kw_event_t: {
+ case tok::kw___vector: {
if (!getLangOpts().CPlusPlus) {
Diag(Tok, diag::err_expected_expression);
return ExprError();
@@ -1168,65 +1123,9 @@
return Result;
}
- case tok::kw___is_abstract: // [GNU] unary-type-trait
- case tok::kw___is_class:
- case tok::kw___is_empty:
- case tok::kw___is_enum:
- case tok::kw___is_interface_class:
- case tok::kw___is_literal:
- case tok::kw___is_arithmetic:
- case tok::kw___is_integral:
- case tok::kw___is_floating_point:
- case tok::kw___is_complete_type:
- case tok::kw___is_void:
- case tok::kw___is_array:
- case tok::kw___is_function:
- case tok::kw___is_reference:
- case tok::kw___is_lvalue_reference:
- case tok::kw___is_rvalue_reference:
- case tok::kw___is_fundamental:
- case tok::kw___is_object:
- case tok::kw___is_scalar:
- case tok::kw___is_compound:
- case tok::kw___is_pointer:
- case tok::kw___is_member_object_pointer:
- case tok::kw___is_member_function_pointer:
- case tok::kw___is_member_pointer:
- case tok::kw___is_const:
- case tok::kw___is_volatile:
- case tok::kw___is_standard_layout:
- case tok::kw___is_signed:
- case tok::kw___is_unsigned:
- case tok::kw___is_literal_type:
- case tok::kw___is_pod:
- case tok::kw___is_polymorphic:
- case tok::kw___is_trivial:
- case tok::kw___is_trivially_copyable:
- case tok::kw___is_union:
- case tok::kw___is_final:
- case tok::kw___is_sealed:
- case tok::kw___has_trivial_constructor:
- case tok::kw___has_trivial_move_constructor:
- case tok::kw___has_trivial_copy:
- case tok::kw___has_trivial_assign:
- case tok::kw___has_trivial_move_assign:
- case tok::kw___has_trivial_destructor:
- case tok::kw___has_nothrow_assign:
- case tok::kw___has_nothrow_move_assign:
- case tok::kw___has_nothrow_copy:
- case tok::kw___has_nothrow_constructor:
- case tok::kw___has_virtual_destructor:
- return ParseUnaryTypeTrait();
-
- case tok::kw___builtin_types_compatible_p:
- case tok::kw___is_base_of:
- case tok::kw___is_same:
- case tok::kw___is_convertible:
- case tok::kw___is_convertible_to:
- case tok::kw___is_trivially_assignable:
- return ParseBinaryTypeTrait();
-
- case tok::kw___is_trivially_constructible:
+#define TYPE_TRAIT(N,Spelling,K) \
+ case tok::kw_##Spelling:
+#include "clang/Basic/TokenKinds.def"
return ParseTypeTrait();
case tok::kw___array_rank:
@@ -1387,21 +1286,20 @@
LHS = ExprError();
}
- SourceLocation CloseLoc = Tok.getLocation();
- if (Tok.is(tok::greatergreatergreater)) {
- ConsumeToken();
+ SourceLocation CloseLoc;
+ if (TryConsumeToken(tok::greatergreatergreater, CloseLoc)) {
} else if (LHS.isInvalid()) {
SkipUntil(tok::greatergreatergreater, StopAtSemi);
} else {
// There was an error closing the brackets
- Diag(Tok, diag::err_expected_ggg);
- Diag(OpenLoc, diag::note_matching) << "<<<";
+ Diag(Tok, diag::err_expected) << tok::greatergreatergreater;
+ Diag(OpenLoc, diag::note_matching) << tok::lesslessless;
SkipUntil(tok::greatergreatergreater, StopAtSemi);
LHS = ExprError();
}
if (!LHS.isInvalid()) {
- if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen, ""))
+ if (ExpectAndConsume(tok::l_paren))
LHS = ExprError();
else
Loc = PrevTokLocation;
@@ -1475,8 +1373,8 @@
(BaseType->isFunctionType() ||
BaseType->isSpecificPlaceholderType(BuiltinType::BoundMember))) {
Diag(OpLoc, diag::err_function_is_not_record)
- << (OpKind == tok::arrow) << Base->getSourceRange()
- << FixItHint::CreateRemoval(OpLoc);
+ << OpKind << Base->getSourceRange()
+ << FixItHint::CreateRemoval(OpLoc);
return ParsePostfixExpressionSuffix(Base);
}
@@ -1597,8 +1495,7 @@
// pathenthesis around type name.
if (OpTok.is(tok::kw_sizeof) || OpTok.is(tok::kw___alignof) ||
OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) {
- bool isAmbiguousTypeId;
- if (isTypeIdInParens(isAmbiguousTypeId)) {
+ if (isTypeIdUnambiguously()) {
DeclSpec DS(AttrFactory);
ParseSpecifierQualifierList(DS);
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
@@ -1617,7 +1514,8 @@
isCastExpr = false;
if (OpTok.is(tok::kw_typeof) && !getLangOpts().CPlusPlus) {
- Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
+ Diag(Tok, diag::err_expected_after) << OpTok.getIdentifierInfo()
+ << tok::l_paren;
return ExprError();
}
@@ -1789,8 +1687,8 @@
// All of these start with an open paren.
if (Tok.isNot(tok::l_paren))
- return ExprError(Diag(Tok, diag::err_expected_lparen_after_id)
- << BuiltinII);
+ return ExprError(Diag(Tok, diag::err_expected_after) << BuiltinII
+ << tok::l_paren);
BalancedDelimiterTracker PT(*this, tok::l_paren);
PT.consumeOpen();
@@ -1802,13 +1700,15 @@
case tok::kw___builtin_va_arg: {
ExprResult Expr(ParseAssignmentExpression());
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
Expr = ExprError();
+ }
TypeResult Ty = ParseTypeName();
if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected_rparen);
+ Diag(Tok, diag::err_expected) << tok::r_paren;
Expr = ExprError();
}
@@ -1826,12 +1726,14 @@
return ExprError();
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
+ }
// We must have at least one identifier here.
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -1853,7 +1755,7 @@
Comps.back().LocStart = ConsumeToken();
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -1902,16 +1804,20 @@
SkipUntil(tok::r_paren, StopAtSemi);
return Cond;
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
+ }
ExprResult Expr1(ParseAssignmentExpression());
if (Expr1.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
return Expr1;
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
+ }
ExprResult Expr2(ParseAssignmentExpression());
if (Expr2.isInvalid()) {
@@ -1919,7 +1825,7 @@
return Expr2;
}
if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected_rparen);
+ Diag(Tok, diag::err_expected) << tok::r_paren;
return ExprError();
}
Res = Actions.ActOnChooseExpr(StartLoc, Cond.take(), Expr1.take(),
@@ -1933,11 +1839,12 @@
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
-
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",
- tok::r_paren))
+
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
-
+ }
+
// Second argument is the type to bitcast to.
TypeResult DestTy = ParseTypeName();
if (DestTy.isInvalid())
@@ -1945,7 +1852,7 @@
// Attempt to consume the r-paren.
if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected_rparen);
+ Diag(Tok, diag::err_expected) << tok::r_paren;
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -1961,11 +1868,12 @@
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
-
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",
- tok::r_paren))
+
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
-
+ }
+
// Second argument is the type to bitcast to.
TypeResult DestTy = ParseTypeName();
if (DestTy.isInvalid())
@@ -1973,7 +1881,7 @@
// Attempt to consume the r-paren.
if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected_rparen);
+ Diag(Tok, diag::err_expected) << tok::r_paren;
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -2042,7 +1950,7 @@
Tok.is(tok::kw___bridge_retained) ||
Tok.is(tok::kw___bridge_retain)));
if (BridgeCast && !getLangOpts().ObjCAutoRefCount) {
- if (Tok.isNot(tok::kw___bridge)) {
+ if (!TryConsumeToken(tok::kw___bridge)) {
StringRef BridgeCastName = Tok.getName();
SourceLocation BridgeKeywordLoc = ConsumeToken();
if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc))
@@ -2050,8 +1958,6 @@
<< BridgeCastName
<< FixItHint::CreateReplacement(BridgeKeywordLoc, "");
}
- else
- ConsumeToken(); // consume __bridge
BridgeCast = false;
}
@@ -2299,7 +2205,7 @@
Diag(KeyLoc, diag::ext_c11_generic_selection);
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return ExprError();
ExprResult ControllingExpr;
@@ -2314,7 +2220,7 @@
}
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "")) {
+ if (ExpectAndConsume(tok::comma)) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -2322,7 +2228,7 @@
SourceLocation DefaultLoc;
TypeVector Types;
ExprVector Exprs;
- while (1) {
+ do {
ParsedType Ty;
if (Tok.is(tok::kw_default)) {
// C11 6.5.1.1p2 "A generic selection shall have no more than one default
@@ -2346,7 +2252,7 @@
}
Types.push_back(Ty);
- if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "")) {
+ if (ExpectAndConsume(tok::colon)) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -2359,11 +2265,7 @@
return ExprError();
}
Exprs.push_back(ER.release());
-
- if (Tok.isNot(tok::comma))
- break;
- ConsumeToken();
- }
+ } while (TryConsumeToken(tok::comma));
T.consumeClose();
if (T.getCloseLocation().isInvalid())
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 5fe47fc..f10ca6a 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -10,12 +10,13 @@
// This file implements the Expression parsing implementation for C++.
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/DeclTemplate.h"
-#include "clang/Parse/Parser.h"
+#include "clang/AST/ASTContext.h"
#include "RAIIObjectsForParser.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
@@ -26,7 +27,9 @@
static int SelectDigraphErrorMessage(tok::TokenKind Kind) {
switch (Kind) {
- case tok::kw_template: return 0;
+ // template name
+ case tok::unknown: return 0;
+ // casts
case tok::kw_const_cast: return 1;
case tok::kw_dynamic_cast: return 2;
case tok::kw_reinterpret_cast: return 3;
@@ -93,7 +96,7 @@
Template, MemberOfUnknownSpecialization))
return;
- FixDigraph(*this, PP, Next, SecondToken, tok::kw_template,
+ FixDigraph(*this, PP, Next, SecondToken, tok::unknown,
/*AtDigraph*/false);
}
@@ -233,12 +236,13 @@
DeclSpec DS(AttrFactory);
SourceLocation DeclLoc = Tok.getLocation();
SourceLocation EndLoc = ParseDecltypeSpecifier(DS);
- if (Tok.isNot(tok::coloncolon)) {
+
+ SourceLocation CCLoc;
+ if (!TryConsumeToken(tok::coloncolon, CCLoc)) {
AnnotateExistingDecltypeSpecifier(DS, DeclLoc, EndLoc);
return false;
}
-
- SourceLocation CCLoc = ConsumeToken();
+
if (Actions.ActOnCXXNestedNameSpecifierDecltype(SS, DS, CCLoc))
SS.SetInvalid(SourceRange(DeclLoc, CCLoc));
@@ -287,19 +291,23 @@
TentativeParsingAction TPA(*this);
SourceLocation TemplateKWLoc = ConsumeToken();
-
+
UnqualifiedId TemplateName;
if (Tok.is(tok::identifier)) {
// Consume the identifier.
TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken();
} else if (Tok.is(tok::kw_operator)) {
- if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType,
+ // We don't need to actually parse the unqualified-id in this case,
+ // because a simple-template-id cannot start with 'operator', but
+ // go ahead and parse it anyway for consistency with the case where
+ // we already annotated the template-id.
+ if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType,
TemplateName)) {
TPA.Commit();
break;
}
-
+
if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId &&
TemplateName.getKind() != UnqualifiedId::IK_LiteralOperatorId) {
Diag(TemplateName.getSourceRange().getBegin(),
@@ -341,10 +349,10 @@
if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
// We have
//
- // simple-template-id '::'
+ // template-id '::'
//
- // So we need to check whether the simple-template-id is of the
- // right kind (it should name a type or be dependent), and then
+ // So we need to check whether the template-id is a simple-template-id of
+ // the right kind (it should name a type or be dependent), and then
// convert it into a type within the nested-name-specifier.
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde)) {
@@ -814,8 +822,7 @@
// to save the necessary state, and restore it later.
EnterExpressionEvaluationContext EC(Actions,
Sema::PotentiallyEvaluated);
- if (Tok.is(tok::equal))
- ConsumeToken();
+ TryConsumeToken(tok::equal);
if (!SkippedInits)
Init = ParseInitializer();
@@ -864,8 +871,8 @@
ConsumeToken();
}
}
- } else if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
+ } else
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
}
// If this is an init capture, process the initialization expression
// right away. For lambda init-captures such as the following:
@@ -988,7 +995,6 @@
ParsedAttributes Attr(AttrFactory);
SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
SourceLocation EllipsisLoc;
-
if (Tok.isNot(tok::r_paren)) {
Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth);
@@ -1002,12 +1008,14 @@
SourceLocation RParenLoc = T.getCloseLocation();
DeclEndLoc = RParenLoc;
+ // GNU-style attributes must be parsed before the mutable specifier to be
+ // compatible with GCC.
+ MaybeParseGNUAttributes(Attr, &DeclEndLoc);
+
// Parse 'mutable'[opt].
SourceLocation MutableLoc;
- if (Tok.is(tok::kw_mutable)) {
- MutableLoc = ConsumeToken();
+ if (TryConsumeToken(tok::kw_mutable, MutableLoc))
DeclEndLoc = MutableLoc;
- }
// Parse exception-specification[opt].
ExceptionSpecificationType ESpecType = EST_None;
@@ -1061,22 +1069,41 @@
LParenLoc, FunLocalRangeEnd, D,
TrailingReturnType),
Attr, DeclEndLoc);
- } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow)) {
- // It's common to forget that one needs '()' before 'mutable' or the
- // result type. Deal with this.
+ } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow) ||
+ Tok.is(tok::kw___attribute) ||
+ (Tok.is(tok::l_square) && NextToken().is(tok::l_square))) {
+ // It's common to forget that one needs '()' before 'mutable', an attribute
+ // specifier, or the result type. Deal with this.
+ unsigned TokKind = 0;
+ switch (Tok.getKind()) {
+ case tok::kw_mutable: TokKind = 0; break;
+ case tok::arrow: TokKind = 1; break;
+ case tok::kw___attribute:
+ case tok::l_square: TokKind = 2; break;
+ default: llvm_unreachable("Unknown token kind");
+ }
+
Diag(Tok, diag::err_lambda_missing_parens)
- << Tok.is(tok::arrow)
+ << TokKind
<< FixItHint::CreateInsertion(Tok.getLocation(), "() ");
SourceLocation DeclLoc = Tok.getLocation();
SourceLocation DeclEndLoc = DeclLoc;
-
+
+ // GNU-style attributes must be parsed before the mutable specifier to be
+ // compatible with GCC.
+ ParsedAttributes Attr(AttrFactory);
+ MaybeParseGNUAttributes(Attr, &DeclEndLoc);
+
// Parse 'mutable', if it's there.
SourceLocation MutableLoc;
if (Tok.is(tok::kw_mutable)) {
MutableLoc = ConsumeToken();
DeclEndLoc = MutableLoc;
}
-
+
+ // Parse attribute-specifier[opt].
+ MaybeParseCXX11Attributes(Attr, &DeclEndLoc);
+
// Parse the return type, if there is one.
TypeResult TrailingReturnType;
if (Tok.is(tok::arrow)) {
@@ -1086,7 +1113,6 @@
DeclEndLoc = Range.getEnd();
}
- ParsedAttributes Attr(AttrFactory);
SourceLocation NoLoc;
D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true,
/*isAmbiguous=*/false,
@@ -1182,8 +1208,8 @@
SourceLocation RAngleBracketLoc = Tok.getLocation();
- if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
- return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
+ if (ExpectAndConsume(tok::greater))
+ return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << tok::less);
SourceLocation LParenLoc, RParenLoc;
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -1667,6 +1693,8 @@
const char *PrevSpec;
unsigned DiagID;
SourceLocation Loc = Tok.getLocation();
+ const clang::PrintingPolicy &Policy =
+ Actions.getASTContext().getPrintingPolicy();
switch (Tok.getKind()) {
case tok::identifier: // foo::bar
@@ -1679,7 +1707,7 @@
case tok::annot_typename: {
if (getTypeAnnotation(Tok))
DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
- getTypeAnnotation(Tok));
+ getTypeAnnotation(Tok), Policy);
else
DS.SetTypeSpecError();
@@ -1693,19 +1721,19 @@
if (Tok.is(tok::less) && getLangOpts().ObjC1)
ParseObjCProtocolQualifiers(DS);
- DS.Finish(Diags, PP);
+ DS.Finish(Diags, PP, Policy);
return;
}
// builtin types
case tok::kw_short:
- DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_long:
- DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw___int64:
- DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_signed:
DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
@@ -1714,47 +1742,47 @@
DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID);
break;
case tok::kw_void:
- DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_char:
- DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_int:
- DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw___int128:
- DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_half:
- DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_float:
- DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_double:
- DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_wchar_t:
- DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_char16_t:
- DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_char32_t:
- DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_bool:
- DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID, Policy);
break;
case tok::annot_decltype:
case tok::kw_decltype:
DS.SetRangeEnd(ParseDecltypeSpecifier(DS));
- return DS.Finish(Diags, PP);
+ return DS.Finish(Diags, PP, Policy);
// GNU typeof support.
case tok::kw_typeof:
ParseTypeofSpecifier(DS);
- DS.Finish(Diags, PP);
+ DS.Finish(Diags, PP, Policy);
return;
}
if (Tok.is(tok::annot_typename))
@@ -1762,7 +1790,7 @@
else
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken();
- DS.Finish(Diags, PP);
+ DS.Finish(Diags, PP, Policy);
}
/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
@@ -1778,7 +1806,7 @@
///
bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
ParseSpecifierQualifierList(DS, AS_none, DSC_type_specifier);
- DS.Finish(Diags, PP);
+ DS.Finish(Diags, PP, Actions.getASTContext().getPrintingPolicy());
return false;
}
@@ -1935,6 +1963,7 @@
TemplateIdAnnotation *TemplateId
= TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds);
+ // FIXME: Store name for literal operator too.
if (Id.getKind() == UnqualifiedId::IK_Identifier) {
TemplateId->Name = Id.Identifier;
TemplateId->Operator = OO_None;
@@ -2158,7 +2187,7 @@
SuffixLoc = ConsumeToken();
TokLocs.push_back(SuffixLoc);
} else {
- Diag(Tok.getLocation(), diag::err_expected_ident);
+ Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
return true;
}
@@ -2183,9 +2212,10 @@
}
Result.setLiteralOperatorId(II, KeywordLoc, SuffixLoc);
- return false;
+
+ return Actions.checkLiteralOperatorId(SS, Result);
}
-
+
// Parse a conversion-function-id.
//
// conversion-function-id: [C++ 12.3.2]
@@ -2678,79 +2708,17 @@
return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, Operand.take());
}
-static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
- switch(kind) {
- default: llvm_unreachable("Not a known unary type trait.");
- case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign;
- case tok::kw___has_nothrow_move_assign: return UTT_HasNothrowMoveAssign;
- case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
- case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
- case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign;
- case tok::kw___has_trivial_move_assign: return UTT_HasTrivialMoveAssign;
- case tok::kw___has_trivial_constructor:
- return UTT_HasTrivialDefaultConstructor;
- case tok::kw___has_trivial_move_constructor:
- return UTT_HasTrivialMoveConstructor;
- case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy;
- case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor;
- case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor;
- case tok::kw___is_abstract: return UTT_IsAbstract;
- case tok::kw___is_arithmetic: return UTT_IsArithmetic;
- case tok::kw___is_array: return UTT_IsArray;
- case tok::kw___is_class: return UTT_IsClass;
- case tok::kw___is_complete_type: return UTT_IsCompleteType;
- case tok::kw___is_compound: return UTT_IsCompound;
- case tok::kw___is_const: return UTT_IsConst;
- case tok::kw___is_empty: return UTT_IsEmpty;
- case tok::kw___is_enum: return UTT_IsEnum;
- case tok::kw___is_final: return UTT_IsFinal;
- case tok::kw___is_floating_point: return UTT_IsFloatingPoint;
- case tok::kw___is_function: return UTT_IsFunction;
- case tok::kw___is_fundamental: return UTT_IsFundamental;
- case tok::kw___is_integral: return UTT_IsIntegral;
- case tok::kw___is_interface_class: return UTT_IsInterfaceClass;
- case tok::kw___is_lvalue_reference: return UTT_IsLvalueReference;
- case tok::kw___is_member_function_pointer: return UTT_IsMemberFunctionPointer;
- case tok::kw___is_member_object_pointer: return UTT_IsMemberObjectPointer;
- case tok::kw___is_member_pointer: return UTT_IsMemberPointer;
- case tok::kw___is_object: return UTT_IsObject;
- case tok::kw___is_literal: return UTT_IsLiteral;
- case tok::kw___is_literal_type: return UTT_IsLiteral;
- case tok::kw___is_pod: return UTT_IsPOD;
- case tok::kw___is_pointer: return UTT_IsPointer;
- case tok::kw___is_polymorphic: return UTT_IsPolymorphic;
- case tok::kw___is_reference: return UTT_IsReference;
- case tok::kw___is_rvalue_reference: return UTT_IsRvalueReference;
- case tok::kw___is_scalar: return UTT_IsScalar;
- case tok::kw___is_sealed: return UTT_IsSealed;
- case tok::kw___is_signed: return UTT_IsSigned;
- case tok::kw___is_standard_layout: return UTT_IsStandardLayout;
- case tok::kw___is_trivial: return UTT_IsTrivial;
- case tok::kw___is_trivially_copyable: return UTT_IsTriviallyCopyable;
- case tok::kw___is_union: return UTT_IsUnion;
- case tok::kw___is_unsigned: return UTT_IsUnsigned;
- case tok::kw___is_void: return UTT_IsVoid;
- case tok::kw___is_volatile: return UTT_IsVolatile;
- }
-}
-
-static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) {
- switch(kind) {
- default: llvm_unreachable("Not a known binary type trait");
- case tok::kw___is_base_of: return BTT_IsBaseOf;
- case tok::kw___is_convertible: return BTT_IsConvertible;
- case tok::kw___is_same: return BTT_IsSame;
- case tok::kw___builtin_types_compatible_p: return BTT_TypeCompatible;
- case tok::kw___is_convertible_to: return BTT_IsConvertibleTo;
- case tok::kw___is_trivially_assignable: return BTT_IsTriviallyAssignable;
- }
-}
-
static TypeTrait TypeTraitFromTokKind(tok::TokenKind kind) {
switch (kind) {
default: llvm_unreachable("Not a known type trait");
- case tok::kw___is_trivially_constructible:
- return TT_IsTriviallyConstructible;
+#define TYPE_TRAIT_1(Spelling, Name, Key) \
+case tok::kw_ ## Spelling: return UTT_ ## Name;
+#define TYPE_TRAIT_2(Spelling, Name, Key) \
+case tok::kw_ ## Spelling: return BTT_ ## Name;
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_N(Spelling, Name, Key) \
+ case tok::kw_ ## Spelling: return TT_ ## Name;
+#include "clang/Basic/TokenKinds.def"
}
}
@@ -2770,87 +2738,33 @@
}
}
-/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
-/// pseudo-functions that allow implementation of the TR1/C++0x type traits
-/// templates.
-///
-/// primary-expression:
-/// [GNU] unary-type-trait '(' type-id ')'
-///
-ExprResult Parser::ParseUnaryTypeTrait() {
- UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
- SourceLocation Loc = ConsumeToken();
-
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
- return ExprError();
-
- // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
- // there will be cryptic errors about mismatched parentheses and missing
- // specifiers.
- TypeResult Ty = ParseTypeName();
-
- T.consumeClose();
-
- if (Ty.isInvalid())
- return ExprError();
-
- return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), T.getCloseLocation());
-}
-
-/// ParseBinaryTypeTrait - Parse the built-in binary type-trait
-/// pseudo-functions that allow implementation of the TR1/C++0x type traits
-/// templates.
-///
-/// primary-expression:
-/// [GNU] binary-type-trait '(' type-id ',' type-id ')'
-///
-ExprResult Parser::ParseBinaryTypeTrait() {
- BinaryTypeTrait BTT = BinaryTypeTraitFromTokKind(Tok.getKind());
- SourceLocation Loc = ConsumeToken();
-
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
- return ExprError();
-
- TypeResult LhsTy = ParseTypeName();
- if (LhsTy.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
+static unsigned TypeTraitArity(tok::TokenKind kind) {
+ switch (kind) {
+ default: llvm_unreachable("Not a known type trait");
+#define TYPE_TRAIT(N,Spelling,K) case tok::kw_##Spelling: return N;
+#include "clang/Basic/TokenKinds.def"
}
-
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
-
- TypeResult RhsTy = ParseTypeName();
- if (RhsTy.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
-
- T.consumeClose();
-
- return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(),
- T.getCloseLocation());
}
/// \brief Parse the built-in type-trait pseudo-functions that allow
/// implementation of the TR1/C++11 type traits templates.
///
/// primary-expression:
+/// unary-type-trait '(' type-id ')'
+/// binary-type-trait '(' type-id ',' type-id ')'
/// type-trait '(' type-id-seq ')'
///
/// type-id-seq:
/// type-id ...[opt] type-id-seq[opt]
///
ExprResult Parser::ParseTypeTrait() {
- TypeTrait Kind = TypeTraitFromTokKind(Tok.getKind());
+ tok::TokenKind Kind = Tok.getKind();
+ unsigned Arity = TypeTraitArity(Kind);
+
SourceLocation Loc = ConsumeToken();
BalancedDelimiterTracker Parens(*this, tok::l_paren);
- if (Parens.expectAndConsume(diag::err_expected_lparen))
+ if (Parens.expectAndConsume())
return ExprError();
SmallVector<ParsedType, 2> Args;
@@ -2873,19 +2787,26 @@
// Add this type to the list of arguments.
Args.push_back(Ty.get());
-
- if (Tok.is(tok::comma)) {
- ConsumeToken();
- continue;
- }
-
- break;
- } while (true);
-
+ } while (TryConsumeToken(tok::comma));
+
if (Parens.consumeClose())
return ExprError();
-
- return Actions.ActOnTypeTrait(Kind, Loc, Args, Parens.getCloseLocation());
+
+ SourceLocation EndLoc = Parens.getCloseLocation();
+
+ if (Arity && Args.size() != Arity) {
+ Diag(EndLoc, diag::err_type_trait_arity)
+ << Arity << 0 << (Arity > 1) << (int)Args.size() << SourceRange(Loc);
+ return ExprError();
+ }
+
+ if (!Arity && Args.empty()) {
+ Diag(EndLoc, diag::err_type_trait_arity)
+ << 1 << 1 << 1 << (int)Args.size() << SourceRange(Loc);
+ return ExprError();
+ }
+
+ return Actions.ActOnTypeTrait(TypeTraitFromTokKind(Kind), Loc, Args, EndLoc);
}
/// ParseArrayTypeTrait - Parse the built-in array type-trait
@@ -2900,7 +2821,7 @@
SourceLocation Loc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return ExprError();
TypeResult Ty = ParseTypeName();
@@ -2917,7 +2838,7 @@
T.getCloseLocation());
}
case ATT_ArrayExtent: {
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) {
+ if (ExpectAndConsume(tok::comma)) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -2943,7 +2864,7 @@
SourceLocation Loc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return ExprError();
ExprResult Expr = ParseExpression();
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index 37f74bb..44053f1 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -105,8 +105,6 @@
return true;
}
}
-
- return true;
}
static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc,
@@ -493,7 +491,7 @@
BalancedDelimiterTracker Braces(*this, tok::l_brace);
if (Braces.consumeOpen()) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return false;
}
@@ -512,7 +510,7 @@
return false;
}
- while (Tok.isNot(tok::eof)) {
+ while (!isEofOrEom()) {
trailingComma = false;
// If we know that this cannot be a designation, just parse the nested
// initializer directly.
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 86f38cf..776dbd6 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -81,9 +81,9 @@
case tok::objc_import:
if (getLangOpts().Modules)
return ParseModuleImport(AtLoc);
-
- // Fall through
-
+ Diag(AtLoc, diag::err_atimport);
+ SkipUntil(tok::semi);
+ return Actions.ConvertDeclToDeclGroup(0);
default:
Diag(AtLoc, diag::err_unexpected_at);
SkipUntil(tok::semi);
@@ -107,7 +107,7 @@
while (1) {
MaybeSkipAttributes(tok::objc_class);
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::semi);
return Actions.ConvertDeclToDeclGroup(0);
}
@@ -115,14 +115,12 @@
ClassLocs.push_back(Tok.getLocation());
ConsumeToken();
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
-
- ConsumeToken();
}
// Consume the ';'.
- if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@class"))
return Actions.ConvertDeclToDeclGroup(0);
return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
@@ -195,7 +193,8 @@
MaybeSkipAttributes(tok::objc_interface);
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident); // missing class or category name.
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing class or category name.
return 0;
}
@@ -222,7 +221,8 @@
categoryLoc = ConsumeToken();
}
else if (!getLangOpts().ObjC2) {
- Diag(Tok, diag::err_expected_ident); // missing category name.
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing category name.
return 0;
}
@@ -274,7 +274,8 @@
}
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident); // missing super class name.
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing super class name.
return 0;
}
superClassId = Tok.getIdentifierInfo();
@@ -328,7 +329,7 @@
MethodImplKind(MethodImplKind) {
}
- void invoke(ParsingFieldDeclarator &FD) {
+ void invoke(ParsingFieldDeclarator &FD) override {
if (FD.D.getIdentifier() == 0) {
P.Diag(AtLoc, diag::err_objc_property_requires_field_name)
<< FD.D.getSourceRange();
@@ -423,7 +424,7 @@
}
// If we got to the end of the file, exit the loop.
- if (Tok.is(tok::eof))
+ if (isEofOrEom())
break;
// Code completion within an Objective-C interface.
@@ -610,8 +611,10 @@
unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter :
diag::err_objc_expected_equal_for_getter;
- if (ExpectAndConsume(tok::equal, DiagID, "", tok::r_paren))
+ if (ExpectAndConsume(tok::equal, DiagID)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
+ }
if (Tok.is(tok::code_completion)) {
if (IsSetter)
@@ -636,10 +639,11 @@
DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
DS.setSetterName(SelIdent);
- if (ExpectAndConsume(tok::colon,
- diag::err_expected_colon_after_setter_name, "",
- tok::r_paren))
+ if (ExpectAndConsume(tok::colon,
+ diag::err_expected_colon_after_setter_name)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
+ }
} else {
DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
DS.setGetterName(SelIdent);
@@ -1054,11 +1058,8 @@
Sema::ObjCArgInfo ArgInfo;
// Each iteration parses a single keyword argument.
- if (Tok.isNot(tok::colon)) {
- Diag(Tok, diag::err_expected_colon);
+ if (ExpectAndConsume(tok::colon))
break;
- }
- ConsumeToken(); // Eat the ':'.
ArgInfo.Type = ParsedType();
if (Tok.is(tok::l_paren)) // Parse the argument type if present.
@@ -1086,7 +1087,8 @@
}
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident); // missing argument name.
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing argument name.
break;
}
@@ -1198,7 +1200,7 @@
}
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::greater, StopAtSemi);
return true;
}
@@ -1207,9 +1209,8 @@
ProtocolLocs.push_back(Tok.getLocation());
ConsumeToken();
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
- ConsumeToken();
}
// Consume the '>'.
@@ -1289,7 +1290,7 @@
BalancedDelimiterTracker T(*this, tok::l_brace);
T.consumeOpen();
// While we still have something to read, read the instance variables.
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// Each iteration of this loop reads one objc-instance-variable-decl.
// Check for extraneous top-level semicolon.
@@ -1299,9 +1300,7 @@
}
// Set the default visibility to private.
- if (Tok.is(tok::at)) { // parse objc-visibility-spec
- ConsumeToken(); // eat the @ sign
-
+ if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtVisibility(getCurScope());
return cutOffParsing();
@@ -1349,7 +1348,7 @@
P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) {
}
- void invoke(ParsingFieldDeclarator &FD) {
+ void invoke(ParsingFieldDeclarator &FD) override {
P.Actions.ActOnObjCContainerStartDefinition(IDecl);
// Install the declarator into the interface decl.
Decl *Field
@@ -1412,16 +1411,15 @@
MaybeSkipAttributes(tok::objc_protocol);
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident); // missing protocol name.
+ Diag(Tok, diag::err_expected) << tok::identifier; // missing protocol name.
return DeclGroupPtrTy();
}
// Save the protocol name, then consume it.
IdentifierInfo *protocolName = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken();
- if (Tok.is(tok::semi)) { // forward declaration of one protocol.
+ if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol.
IdentifierLocPair ProtoInfo(protocolName, nameLoc);
- ConsumeToken();
return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
attrs.getList());
}
@@ -1436,7 +1434,7 @@
while (1) {
ConsumeToken(); // the ','
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::semi);
return DeclGroupPtrTy();
}
@@ -1448,7 +1446,7 @@
break;
}
// Consume the ';'.
- if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol"))
return DeclGroupPtrTy();
return Actions.ActOnForwardProtocolDeclaration(AtLoc,
@@ -1505,7 +1503,8 @@
MaybeSkipAttributes(tok::objc_implementation);
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident); // missing class or category name.
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing class or category name.
return DeclGroupPtrTy();
}
// We have a class or category name - consume it.
@@ -1529,11 +1528,12 @@
categoryId = Tok.getIdentifierInfo();
categoryLoc = ConsumeToken();
} else {
- Diag(Tok, diag::err_expected_ident); // missing category name.
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing category name.
return DeclGroupPtrTy();
}
if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected_rparen);
+ Diag(Tok, diag::err_expected) << tok::r_paren;
SkipUntil(tok::r_paren); // don't stop at ';'
return DeclGroupPtrTy();
}
@@ -1552,11 +1552,11 @@
// We have a class implementation
SourceLocation superClassLoc;
IdentifierInfo *superClassId = 0;
- if (Tok.is(tok::colon)) {
+ if (TryConsumeToken(tok::colon)) {
// We have a super class
- ConsumeToken();
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident); // missing super class name.
+ Diag(Tok, diag::err_expected)
+ << tok::identifier; // missing super class name.
return DeclGroupPtrTy();
}
superClassId = Tok.getIdentifierInfo();
@@ -1582,7 +1582,7 @@
{
ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl);
- while (!ObjCImplParsing.isFinished() && Tok.isNot(tok::eof)) {
+ while (!ObjCImplParsing.isFinished() && !isEofOrEom()) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
MaybeParseMicrosoftAttributes(attrs);
@@ -1612,7 +1612,7 @@
Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() {
if (!Finished) {
finish(P.Tok.getLocation());
- if (P.Tok.is(tok::eof)) {
+ if (P.isEofOrEom()) {
P.Diag(P.Tok, diag::err_objc_missing_end)
<< FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n");
P.Diag(Dcl->getLocStart(), diag::note_objc_container_start)
@@ -1655,19 +1655,18 @@
"ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
ConsumeToken(); // consume compatibility_alias
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
return 0;
}
IdentifierInfo *aliasId = Tok.getIdentifierInfo();
SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
return 0;
}
IdentifierInfo *classId = Tok.getIdentifierInfo();
SourceLocation classLoc = ConsumeToken(); // consume class-name;
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- "@compatibility_alias");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias");
return Actions.ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc,
classId, classLoc);
}
@@ -1705,10 +1704,8 @@
IdentifierInfo *propertyId = Tok.getIdentifierInfo();
SourceLocation propertyLoc = ConsumeToken(); // consume property name
SourceLocation propertyIvarLoc;
- if (Tok.is(tok::equal)) {
+ if (TryConsumeToken(tok::equal)) {
// property '=' ivar-name
- ConsumeToken(); // consume '='
-
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId);
cutOffParsing();
@@ -1716,7 +1713,7 @@
}
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
break;
}
propertyIvar = Tok.getIdentifierInfo();
@@ -1728,7 +1725,7 @@
break;
ConsumeToken(); // consume ','
}
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@synthesize");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "@synthesize");
return 0;
}
@@ -1751,7 +1748,7 @@
}
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::semi);
return 0;
}
@@ -1765,7 +1762,7 @@
break;
ConsumeToken(); // consume ','
}
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@dynamic");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "@dynamic");
return 0;
}
@@ -1783,7 +1780,7 @@
}
}
// consume ';'
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@throw");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "@throw");
return Actions.ActOnObjCAtThrowStmt(atLoc, Res.take(), getCurScope());
}
@@ -1806,7 +1803,7 @@
ConsumeParen(); // ')'
} else {
if (!operand.isInvalid())
- Diag(Tok, diag::err_expected_rparen);
+ Diag(Tok, diag::err_expected) << tok::r_paren;
// Skip forward until we see a left brace, but don't consume it.
SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
@@ -1815,7 +1812,7 @@
// Require a compound statement.
if (Tok.isNot(tok::l_brace)) {
if (!operand.isInvalid())
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return StmtError();
}
@@ -1855,7 +1852,7 @@
ConsumeToken(); // consume try
if (Tok.isNot(tok::l_brace)) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return StmtError();
}
StmtVector CatchStmts;
@@ -1905,7 +1902,7 @@
if (Tok.is(tok::l_brace))
CatchBody = ParseCompoundStatementBody();
else
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
if (CatchBody.isInvalid())
CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
@@ -1931,7 +1928,7 @@
if (Tok.is(tok::l_brace))
FinallyBody = ParseCompoundStatementBody();
else
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
if (FinallyBody.isInvalid())
FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
@@ -1957,7 +1954,7 @@
Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
ConsumeToken(); // consume autoreleasepool
if (Tok.isNot(tok::l_brace)) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return StmtError();
}
// Enter a scope to hold everything within the compound stmt. Compound
@@ -2478,8 +2475,7 @@
KeyIdents.push_back(selIdent);
KeyLocs.push_back(Loc);
- if (Tok.isNot(tok::colon)) {
- Diag(Tok, diag::err_expected_colon);
+ if (ExpectAndConsume(tok::colon)) {
// We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
// the enclosing expression.
@@ -2487,7 +2483,6 @@
return ExprError();
}
- ConsumeToken(); // Eat the ':'.
/// Parse the expression after ':'
if (Tok.is(tok::code_completion)) {
@@ -2572,7 +2567,7 @@
KeyExprs.push_back(Res.release());
}
} else if (!selIdent) {
- Diag(Tok, diag::err_expected_ident); // missing selector name.
+ Diag(Tok, diag::err_expected) << tok::identifier; // missing selector name.
// We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
@@ -2582,10 +2577,8 @@
}
if (Tok.isNot(tok::r_square)) {
- if (Tok.is(tok::identifier))
- Diag(Tok, diag::err_expected_colon);
- else
- Diag(Tok, diag::err_expected_rsquare);
+ Diag(Tok, diag::err_expected)
+ << (Tok.is(tok::identifier) ? tok::colon : tok::r_square);
// We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
// the enclosing expression.
@@ -2730,7 +2723,8 @@
if (Tok.is(tok::comma))
ConsumeToken(); // Eat the ','.
else if (Tok.isNot(tok::r_square))
- return ExprError(Diag(Tok, diag::err_expected_rsquare_or_comma));
+ return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_square
+ << tok::comma);
}
SourceLocation EndLoc = ConsumeBracket(); // location of ']'
MultiExprArg Args(ElementExprs);
@@ -2755,10 +2749,7 @@
}
}
- if (Tok.is(tok::colon)) {
- ConsumeToken();
- } else {
- Diag(Tok, diag::err_expected_colon);
+ if (ExpectAndConsume(tok::colon)) {
SkipUntil(tok::r_brace, StopAtSemi);
return ExprError();
}
@@ -2774,20 +2765,19 @@
// Parse the ellipsis that designates this as a pack expansion.
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis) && getLangOpts().CPlusPlus)
- EllipsisLoc = ConsumeToken();
-
+ if (getLangOpts().CPlusPlus)
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
+
// We have a valid expression. Collect it in a vector so we can
// build the argument list.
ObjCDictionaryElement Element = {
KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None
};
Elements.push_back(Element);
-
- if (Tok.is(tok::comma))
- ConsumeToken(); // Eat the ','.
- else if (Tok.isNot(tok::r_brace))
- return ExprError(Diag(Tok, diag::err_expected_rbrace_or_comma));
+
+ if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace))
+ return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_brace
+ << tok::comma);
}
SourceLocation EndLoc = ConsumeBrace();
@@ -2834,7 +2824,7 @@
T.consumeOpen();
if (Tok.isNot(tok::identifier))
- return ExprError(Diag(Tok, diag::err_expected_ident));
+ return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
IdentifierInfo *protocolId = Tok.getIdentifierInfo();
SourceLocation ProtoIdLoc = ConsumeToken();
@@ -2869,20 +2859,19 @@
IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
if (!SelIdent && // missing selector name.
Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
- return ExprError(Diag(Tok, diag::err_expected_ident));
+ return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
KeyIdents.push_back(SelIdent);
unsigned nColons = 0;
if (Tok.isNot(tok::r_paren)) {
while (1) {
- if (Tok.is(tok::coloncolon)) { // Handle :: in C++.
+ if (TryConsumeToken(tok::coloncolon)) { // Handle :: in C++.
++nColons;
KeyIdents.push_back(0);
- } else if (Tok.isNot(tok::colon))
- return ExprError(Diag(Tok, diag::err_expected_colon));
-
+ } else if (ExpectAndConsume(tok::colon)) // Otherwise expect ':'.
+ return ExprError();
++nColons;
- ConsumeToken(); // Eat the ':' or '::'.
+
if (Tok.is(tok::r_paren))
break;
@@ -2931,7 +2920,7 @@
assert((Tok.is(tok::l_brace) || Tok.is(tok::kw_try) ||
Tok.is(tok::colon)) &&
"Inline objective-c method not starting with '{' or 'try' or ':'");
- // Enter a scope for the method or c-fucntion body.
+ // Enter a scope for the method or c-function body.
ParseScope BodyScope(this,
parseMethod
? Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope
@@ -2944,11 +2933,11 @@
else
Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl);
if (Tok.is(tok::kw_try))
- MCDecl = ParseFunctionTryBlock(MCDecl, BodyScope);
+ ParseFunctionTryBlock(MCDecl, BodyScope);
else {
if (Tok.is(tok::colon))
ParseConstructorInitializer(MCDecl);
- MCDecl = ParseFunctionStatementBody(MCDecl, BodyScope);
+ ParseFunctionStatementBody(MCDecl, BodyScope);
}
if (Tok.getLocation() != OrigLoc) {
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index 89e4147..f1b6107 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -12,12 +12,12 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTConsumer.h"
+#include "RAIIObjectsForParser.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/PointerIntPair.h"
-#include "RAIIObjectsForParser.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -60,6 +60,7 @@
Diag(Tok, diag::err_omp_unknown_directive);
break;
case OMPD_parallel:
+ case OMPD_simd:
case OMPD_task:
case NUM_OPENMP_DIRECTIVES:
Diag(Tok, diag::err_omp_unexpected_directive)
@@ -114,7 +115,8 @@
}
SkipUntil(tok::annot_pragma_openmp_end);
break;
- case OMPD_parallel: {
+ case OMPD_parallel:
+ case OMPD_simd: {
ConsumeToken();
Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope());
@@ -225,8 +227,9 @@
IsCorrect = false;
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
- Diag(PrevTok.getLocation(), diag::err_expected_ident)
- << SourceRange(PrevTok.getLocation(), PrevTokLocation);
+ Diag(PrevTok.getLocation(), diag::err_expected)
+ << tok::identifier
+ << SourceRange(PrevTok.getLocation(), PrevTokLocation);
} else {
DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS,
@@ -241,7 +244,7 @@
}
if (NoIdentIsFound) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
IsCorrect = false;
}
@@ -254,7 +257,8 @@
/// \brief Parsing of OpenMP clauses.
///
/// clause:
-/// default-clause|private-clause|firstprivate-clause|shared-clause
+/// if-clause | num_threads-clause | safelen-clause | default-clause |
+/// private-clause | firstprivate-clause | shared-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@@ -268,10 +272,25 @@
}
switch (CKind) {
+ case OMPC_if:
+ case OMPC_num_threads:
+ case OMPC_safelen:
+ // OpenMP [2.5, Restrictions]
+ // At most one if clause can appear on the directive.
+ // At most one num_threads clause can appear on the directive.
+ // OpenMP [2.8.1, simd construct, Restrictions]
+ // Only one safelen clause can appear on a simd directive.
+ if (!FirstClause) {
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
+ }
+
+ Clause = ParseOpenMPSingleExprClause(CKind);
+ break;
case OMPC_default:
- // OpenMP [2.9.3.1, Restrictions]
- // Only a single default clause may be specified on a parallel or task
- // directive.
+ // OpenMP [2.14.3.1, Restrictions]
+ // Only a single default clause may be specified on a parallel, task or
+ // teams directive.
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
@@ -282,6 +301,7 @@
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
+ case OMPC_copyin:
Clause = ParseOpenMPVarListClause(CKind);
break;
case OMPC_unknown:
@@ -299,6 +319,41 @@
return ErrorFound ? 0 : Clause;
}
+/// \brief Parsing of OpenMP clauses with single expressions like 'if',
+/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
+/// 'thread_limit'.
+///
+/// if-clause:
+/// 'if' '(' expression ')'
+///
+/// num_threads-clause:
+/// 'num_threads' '(' expression ')'
+///
+/// safelen-clause:
+/// 'safelen' '(' expression ')'
+///
+OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
+ SourceLocation Loc = ConsumeToken();
+
+ BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ getOpenMPClauseName(Kind)))
+ return 0;
+
+ ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
+ ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+
+ // Parse ')'.
+ T.consumeClose();
+
+ if (Val.isInvalid())
+ return 0;
+
+ return Actions.ActOnOpenMPSingleExprClause(Kind, Val.take(), Loc,
+ T.getOpenLocation(),
+ T.getCloseLocation());
+}
+
/// \brief Parsing of simple OpenMP clauses like 'default'.
///
/// default-clause:
@@ -366,7 +421,7 @@
} else if (Tok.isNot(tok::r_paren) &&
Tok.isNot(tok::annot_pragma_openmp_end)) {
Diag(Tok, diag::err_omp_expected_punc)
- << 1 << getOpenMPClauseName(Kind);
+ << getOpenMPClauseName(Kind);
}
}
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 8a374e0..29e1771 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "ParsePragma.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
@@ -19,6 +18,208 @@
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
+namespace {
+
+struct PragmaAlignHandler : public PragmaHandler {
+ explicit PragmaAlignHandler() : PragmaHandler("align") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaGCCVisibilityHandler : public PragmaHandler {
+ explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaOptionsHandler : public PragmaHandler {
+ explicit PragmaOptionsHandler() : PragmaHandler("options") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaPackHandler : public PragmaHandler {
+ explicit PragmaPackHandler() : PragmaHandler("pack") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaMSStructHandler : public PragmaHandler {
+ explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaUnusedHandler : public PragmaHandler {
+ PragmaUnusedHandler() : PragmaHandler("unused") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaWeakHandler : public PragmaHandler {
+ explicit PragmaWeakHandler() : PragmaHandler("weak") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaRedefineExtnameHandler : public PragmaHandler {
+ explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaOpenCLExtensionHandler : public PragmaHandler {
+ PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+
+struct PragmaFPContractHandler : public PragmaHandler {
+ PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaNoOpenMPHandler : public PragmaHandler {
+ PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaOpenMPHandler : public PragmaHandler {
+ PragmaOpenMPHandler() : PragmaHandler("omp") { }
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+/// PragmaCommentHandler - "\#pragma comment ...".
+struct PragmaCommentHandler : public PragmaHandler {
+ PragmaCommentHandler(Sema &Actions)
+ : PragmaHandler("comment"), Actions(Actions) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+private:
+ Sema &Actions;
+};
+
+struct PragmaDetectMismatchHandler : public PragmaHandler {
+ PragmaDetectMismatchHandler(Sema &Actions)
+ : PragmaHandler("detect_mismatch"), Actions(Actions) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+private:
+ Sema &Actions;
+};
+
+struct PragmaMSPointersToMembers : public PragmaHandler {
+ explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaMSVtorDisp : public PragmaHandler {
+ explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+} // end namespace
+
+void Parser::initializePragmaHandlers() {
+ AlignHandler.reset(new PragmaAlignHandler());
+ PP.AddPragmaHandler(AlignHandler.get());
+
+ GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
+ PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
+
+ OptionsHandler.reset(new PragmaOptionsHandler());
+ PP.AddPragmaHandler(OptionsHandler.get());
+
+ PackHandler.reset(new PragmaPackHandler());
+ PP.AddPragmaHandler(PackHandler.get());
+
+ MSStructHandler.reset(new PragmaMSStructHandler());
+ PP.AddPragmaHandler(MSStructHandler.get());
+
+ UnusedHandler.reset(new PragmaUnusedHandler());
+ PP.AddPragmaHandler(UnusedHandler.get());
+
+ WeakHandler.reset(new PragmaWeakHandler());
+ PP.AddPragmaHandler(WeakHandler.get());
+
+ RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
+ PP.AddPragmaHandler(RedefineExtnameHandler.get());
+
+ FPContractHandler.reset(new PragmaFPContractHandler());
+ PP.AddPragmaHandler("STDC", FPContractHandler.get());
+
+ if (getLangOpts().OpenCL) {
+ OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
+ PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
+
+ PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
+ }
+ if (getLangOpts().OpenMP)
+ OpenMPHandler.reset(new PragmaOpenMPHandler());
+ else
+ OpenMPHandler.reset(new PragmaNoOpenMPHandler());
+ PP.AddPragmaHandler(OpenMPHandler.get());
+
+ if (getLangOpts().MicrosoftExt) {
+ MSCommentHandler.reset(new PragmaCommentHandler(Actions));
+ PP.AddPragmaHandler(MSCommentHandler.get());
+ MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
+ PP.AddPragmaHandler(MSDetectMismatchHandler.get());
+ MSPointersToMembers.reset(new PragmaMSPointersToMembers());
+ PP.AddPragmaHandler(MSPointersToMembers.get());
+ MSVtorDisp.reset(new PragmaMSVtorDisp());
+ PP.AddPragmaHandler(MSVtorDisp.get());
+ }
+}
+
+void Parser::resetPragmaHandlers() {
+ // Remove the pragma handlers we installed.
+ PP.RemovePragmaHandler(AlignHandler.get());
+ AlignHandler.reset();
+ PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
+ GCCVisibilityHandler.reset();
+ PP.RemovePragmaHandler(OptionsHandler.get());
+ OptionsHandler.reset();
+ PP.RemovePragmaHandler(PackHandler.get());
+ PackHandler.reset();
+ PP.RemovePragmaHandler(MSStructHandler.get());
+ MSStructHandler.reset();
+ PP.RemovePragmaHandler(UnusedHandler.get());
+ UnusedHandler.reset();
+ PP.RemovePragmaHandler(WeakHandler.get());
+ WeakHandler.reset();
+ PP.RemovePragmaHandler(RedefineExtnameHandler.get());
+ RedefineExtnameHandler.reset();
+
+ if (getLangOpts().OpenCL) {
+ PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
+ OpenCLExtensionHandler.reset();
+ PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
+ }
+ PP.RemovePragmaHandler(OpenMPHandler.get());
+ OpenMPHandler.reset();
+
+ if (getLangOpts().MicrosoftExt) {
+ PP.RemovePragmaHandler(MSCommentHandler.get());
+ MSCommentHandler.reset();
+ PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
+ MSDetectMismatchHandler.reset();
+ PP.RemovePragmaHandler(MSPointersToMembers.get());
+ MSPointersToMembers.reset();
+ PP.RemovePragmaHandler(MSVtorDisp.get());
+ MSVtorDisp.reset();
+ }
+
+ PP.RemovePragmaHandler("STDC", FPContractHandler.get());
+ FPContractHandler.reset();
+}
+
/// \brief Handle the annotation token produced for #pragma unused(...)
///
/// Each annot_pragma_unused is followed by the argument token so e.g.
@@ -130,7 +331,7 @@
ConsumeToken();
if (Tok.isNot(tok::l_brace)) {
- PP.Diag(Tok, diag::err_expected_lbrace);
+ PP.Diag(Tok, diag::err_expected) << tok::l_brace;
return StmtError();
}
@@ -180,7 +381,24 @@
}
}
+void Parser::HandlePragmaMSPointersToMembers() {
+ assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
+ LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
+ static_cast<LangOptions::PragmaMSPointersToMembersKind>(
+ reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
+ SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
+ Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
+}
+void Parser::HandlePragmaMSVtorDisp() {
+ assert(Tok.is(tok::annot_pragma_ms_vtordisp));
+ uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
+ Sema::PragmaVtorDispKind Kind =
+ static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
+ MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
+ SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
+ Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
+}
// #pragma GCC visibility comes in two variants:
// 'push' '(' [visibility] ')'
@@ -283,7 +501,7 @@
} else if (II->isStr("pop")) {
Kind = Sema::PPK_Pop;
} else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
return;
}
PP.Lex(Tok);
@@ -530,7 +748,7 @@
}
// Illegal token!
- PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
return;
}
@@ -799,6 +1017,193 @@
/*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
}
+/// \brief Handle '#pragma pointers_to_members'
+// The grammar for this pragma is as follows:
+//
+// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
+//
+// #pragma pointers_to_members '(' 'best_case' ')'
+// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
+// #pragma pointers_to_members '(' inheritance-model ')'
+void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ SourceLocation PointersToMembersLoc = Tok.getLocation();
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
+ << "pointers_to_members";
+ return;
+ }
+ PP.Lex(Tok);
+ const IdentifierInfo *Arg = Tok.getIdentifierInfo();
+ if (!Arg) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
+ << "pointers_to_members";
+ return;
+ }
+ PP.Lex(Tok);
+
+ LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
+ if (Arg->isStr("best_case")) {
+ RepresentationMethod = LangOptions::PPTMK_BestCase;
+ } else {
+ if (Arg->isStr("full_generality")) {
+ if (Tok.is(tok::comma)) {
+ PP.Lex(Tok);
+
+ Arg = Tok.getIdentifierInfo();
+ if (!Arg) {
+ PP.Diag(Tok.getLocation(),
+ diag::err_pragma_pointers_to_members_unknown_kind)
+ << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
+ return;
+ }
+ PP.Lex(Tok);
+ } else if (Tok.is(tok::r_paren)) {
+ // #pragma pointers_to_members(full_generality) implicitly specifies
+ // virtual_inheritance.
+ Arg = 0;
+ RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
+ } else {
+ PP.Diag(Tok.getLocation(), diag::err_expected_punc)
+ << "full_generality";
+ return;
+ }
+ }
+
+ if (Arg) {
+ if (Arg->isStr("single_inheritance")) {
+ RepresentationMethod =
+ LangOptions::PPTMK_FullGeneralitySingleInheritance;
+ } else if (Arg->isStr("multiple_inheritance")) {
+ RepresentationMethod =
+ LangOptions::PPTMK_FullGeneralityMultipleInheritance;
+ } else if (Arg->isStr("virtual_inheritance")) {
+ RepresentationMethod =
+ LangOptions::PPTMK_FullGeneralityVirtualInheritance;
+ } else {
+ PP.Diag(Tok.getLocation(),
+ diag::err_pragma_pointers_to_members_unknown_kind)
+ << Arg << /*HasPointerDeclaration*/ 1;
+ return;
+ }
+ }
+ }
+
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
+ << (Arg ? Arg->getName() : "full_generality");
+ return;
+ }
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "pointers_to_members";
+ return;
+ }
+
+ Token AnnotTok;
+ AnnotTok.startToken();
+ AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
+ AnnotTok.setLocation(PointersToMembersLoc);
+ AnnotTok.setAnnotationValue(
+ reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
+ PP.EnterToken(AnnotTok);
+}
+
+/// \brief Handle '#pragma vtordisp'
+// The grammar for this pragma is as follows:
+//
+// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
+//
+// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
+// #pragma vtordisp '(' 'pop' ')'
+// #pragma vtordisp '(' ')'
+void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ SourceLocation VtorDispLoc = Tok.getLocation();
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
+ return;
+ }
+ PP.Lex(Tok);
+
+ Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II) {
+ if (II->isStr("push")) {
+ // #pragma vtordisp(push, mode)
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::comma)) {
+ PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
+ return;
+ }
+ PP.Lex(Tok);
+ Kind = Sema::PVDK_Push;
+ // not push, could be on/off
+ } else if (II->isStr("pop")) {
+ // #pragma vtordisp(pop)
+ PP.Lex(Tok);
+ Kind = Sema::PVDK_Pop;
+ }
+ // not push or pop, could be on/off
+ } else {
+ if (Tok.is(tok::r_paren)) {
+ // #pragma vtordisp()
+ Kind = Sema::PVDK_Reset;
+ }
+ }
+
+
+ uint64_t Value = 0;
+ if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II && II->isStr("off")) {
+ PP.Lex(Tok);
+ Value = 0;
+ } else if (II && II->isStr("on")) {
+ PP.Lex(Tok);
+ Value = 1;
+ } else if (Tok.is(tok::numeric_constant) &&
+ PP.parseSimpleIntegerLiteral(Tok, Value)) {
+ if (Value > 2) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
+ << 0 << 2 << "vtordisp";
+ return;
+ }
+ } else {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
+ << "vtordisp";
+ return;
+ }
+ }
+
+ // Finish the pragma: ')' $
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
+ return;
+ }
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "vtordisp";
+ return;
+ }
+
+ // Enter the annotation.
+ Token AnnotTok;
+ AnnotTok.startToken();
+ AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
+ AnnotTok.setLocation(VtorDispLoc);
+ AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
+ static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
+ PP.EnterToken(AnnotTok);
+}
+
/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
///
/// The syntax is:
@@ -815,7 +1220,7 @@
SourceLocation CommentLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.isNot(tok::l_paren)) {
- PP.Diag(CommentLoc, diag::err_expected_lparen);
+ PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
return;
}
@@ -838,7 +1243,7 @@
return;
if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_expected_rparen);
+ PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
return;
}
PP.Lex(Tok); // Eat the r_paren.
diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h
deleted file mode 100644
index b41450f..0000000
--- a/lib/Parse/ParsePragma.h
+++ /dev/null
@@ -1,139 +0,0 @@
-//===---- ParserPragmas.h - Language specific pragmas -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines #pragma handlers for language specific pragmas.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_PARSE_PARSEPRAGMA_H
-#define LLVM_CLANG_PARSE_PARSEPRAGMA_H
-
-#include "clang/Lex/Pragma.h"
-
-namespace clang {
- class Sema;
- class Parser;
-
-class PragmaAlignHandler : public PragmaHandler {
-public:
- explicit PragmaAlignHandler() : PragmaHandler("align") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaGCCVisibilityHandler : public PragmaHandler {
-public:
- explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaOptionsHandler : public PragmaHandler {
-public:
- explicit PragmaOptionsHandler() : PragmaHandler("options") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaPackHandler : public PragmaHandler {
-public:
- explicit PragmaPackHandler() : PragmaHandler("pack") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaMSStructHandler : public PragmaHandler {
-public:
- explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaUnusedHandler : public PragmaHandler {
-public:
- PragmaUnusedHandler() : PragmaHandler("unused") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaWeakHandler : public PragmaHandler {
-public:
- explicit PragmaWeakHandler() : PragmaHandler("weak") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaRedefineExtnameHandler : public PragmaHandler {
-public:
- explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
-
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaOpenCLExtensionHandler : public PragmaHandler {
-public:
- PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-
-class PragmaFPContractHandler : public PragmaHandler {
-public:
- PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaNoOpenMPHandler : public PragmaHandler {
-public:
- PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-class PragmaOpenMPHandler : public PragmaHandler {
-public:
- PragmaOpenMPHandler() : PragmaHandler("omp") { }
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-};
-
-/// PragmaCommentHandler - "\#pragma comment ...".
-class PragmaCommentHandler : public PragmaHandler {
-public:
- PragmaCommentHandler(Sema &Actions)
- : PragmaHandler("comment"), Actions(Actions) {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-private:
- Sema &Actions;
-};
-
-class PragmaDetectMismatchHandler : public PragmaHandler {
-public:
- PragmaDetectMismatchHandler(Sema &Actions)
- : PragmaHandler("detect_mismatch"), Actions(Actions) {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
-private:
- Sema &Actions;
-};
-
-} // end namespace clang
-
-#endif
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index d1f2138..7254eb3 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -23,6 +23,7 @@
#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/TypoCorrection.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectFileInfo.h"
@@ -34,7 +35,6 @@
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
-#include "llvm/ADT/SmallString.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -142,7 +142,7 @@
WantCXXNamedCasts = false;
}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
if (FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>())
return !candidate.getCorrectionSpecifier() || isa<ObjCIvarDecl>(FD);
if (NextToken.is(tok::equal))
@@ -345,12 +345,15 @@
ProhibitAttributes(Attrs);
return ParseOpenMPDeclarativeOrExecutableDirective();
+ case tok::annot_pragma_ms_pointers_to_members:
+ ProhibitAttributes(Attrs);
+ HandlePragmaMSPointersToMembers();
+ return StmtEmpty();
+
}
// If we reached this code, the statement must end in a semicolon.
- if (Tok.is(tok::semi)) {
- ConsumeToken();
- } else if (!Res.isInvalid()) {
+ if (!TryConsumeToken(tok::semi) && !Res.isInvalid()) {
// If the result was valid, then we do want to diagnose this. Use
// ExpectAndConsume to emit the diagnostic, even though we know it won't
// succeed.
@@ -412,7 +415,7 @@
///
StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) {
if(Tok.isNot(tok::l_brace))
- return StmtError(Diag(Tok,diag::err_expected_lbrace));
+ return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
StmtResult TryBlock(ParseCompoundStatement());
if(TryBlock.isInvalid())
@@ -449,7 +452,7 @@
raii2(Ident___exception_code, false),
raii3(Ident_GetExceptionCode, false);
- if(ExpectAndConsume(tok::l_paren,diag::err_expected_lparen))
+ if (ExpectAndConsume(tok::l_paren))
return StmtError();
ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope);
@@ -470,7 +473,7 @@
if(FilterExpr.isInvalid())
return StmtError();
- if(ExpectAndConsume(tok::r_paren,diag::err_expected_rparen))
+ if (ExpectAndConsume(tok::r_paren))
return StmtError();
StmtResult Block(ParseCompoundStatement());
@@ -543,7 +546,7 @@
SubStmt = Actions.ProcessStmtAttributes(
SubStmt.get(), TempAttrs.getList(), TempAttrs.Range);
} else {
- Diag(Tok, diag::err_expected_semi_after) << "__attribute__";
+ Diag(Tok, diag::err_expected_after) << "__attribute__" << tok::semi;
}
}
@@ -624,10 +627,8 @@
// GNU case range extension.
SourceLocation DotDotDotLoc;
ExprResult RHS;
- if (Tok.is(tok::ellipsis)) {
- Diag(Tok, diag::ext_gnu_case_range);
- DotDotDotLoc = ConsumeToken();
-
+ if (TryConsumeToken(tok::ellipsis, DotDotDotLoc)) {
+ Diag(DotDotDotLoc, diag::ext_gnu_case_range);
RHS = ParseConstantExpression();
if (RHS.isInvalid()) {
SkipUntil(tok::colon, StopAtSemi);
@@ -637,18 +638,17 @@
ColonProtection.restore();
- if (Tok.is(tok::colon)) {
- ColonLoc = ConsumeToken();
-
- // Treat "case blah;" as a typo for "case blah:".
- } else if (Tok.is(tok::semi)) {
- ColonLoc = ConsumeToken();
- Diag(ColonLoc, diag::err_expected_colon_after) << "'case'"
- << FixItHint::CreateReplacement(ColonLoc, ":");
+ if (TryConsumeToken(tok::colon, ColonLoc)) {
+ } else if (TryConsumeToken(tok::semi, ColonLoc)) {
+ // Treat "case blah;" as a typo for "case blah:".
+ Diag(ColonLoc, diag::err_expected_after)
+ << "'case'" << tok::colon
+ << FixItHint::CreateReplacement(ColonLoc, ":");
} else {
SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
- Diag(ExpectedLoc, diag::err_expected_colon_after) << "'case'"
- << FixItHint::CreateInsertion(ExpectedLoc, ":");
+ Diag(ExpectedLoc, diag::err_expected_after)
+ << "'case'" << tok::colon
+ << FixItHint::CreateInsertion(ExpectedLoc, ":");
ColonLoc = ExpectedLoc;
}
@@ -713,18 +713,17 @@
SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'.
SourceLocation ColonLoc;
- if (Tok.is(tok::colon)) {
- ColonLoc = ConsumeToken();
-
- // Treat "default;" as a typo for "default:".
- } else if (Tok.is(tok::semi)) {
- ColonLoc = ConsumeToken();
- Diag(ColonLoc, diag::err_expected_colon_after) << "'default'"
- << FixItHint::CreateReplacement(ColonLoc, ":");
+ if (TryConsumeToken(tok::colon, ColonLoc)) {
+ } else if (TryConsumeToken(tok::semi, ColonLoc)) {
+ // Treat "default;" as a typo for "default:".
+ Diag(ColonLoc, diag::err_expected_after)
+ << "'default'" << tok::colon
+ << FixItHint::CreateReplacement(ColonLoc, ":");
} else {
SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
- Diag(ExpectedLoc, diag::err_expected_colon_after) << "'default'"
- << FixItHint::CreateInsertion(ExpectedLoc, ":");
+ Diag(ExpectedLoc, diag::err_expected_after)
+ << "'default'" << tok::colon
+ << FixItHint::CreateInsertion(ExpectedLoc, ":");
ColonLoc = ExpectedLoc;
}
@@ -826,6 +825,9 @@
case tok::annot_pragma_fp_contract:
HandlePragmaFPContract();
break;
+ case tok::annot_pragma_ms_pointers_to_members:
+ HandlePragmaMSPointersToMembers();
+ break;
default:
checkForPragmas = false;
break;
@@ -867,7 +869,7 @@
SmallVector<Decl *, 8> DeclsInGroup;
while (1) {
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
break;
}
@@ -875,9 +877,8 @@
SourceLocation IdLoc = ConsumeToken();
DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc));
- if (!Tok.is(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
- ConsumeToken();
}
DeclSpec DS(AttrFactory);
@@ -890,7 +891,7 @@
Stmts.push_back(R.release());
}
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
if (Tok.is(tok::annot_pragma_unused)) {
HandlePragmaUnused();
continue;
@@ -1077,8 +1078,7 @@
// would have to notify ParseStatement not to create a new scope. It's
// simpler to let it create a new scope.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXX && Tok.isNot(tok::l_brace));
+ ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
// Read the 'then' stmt.
SourceLocation ThenStmtLoc = Tok.getLocation();
@@ -1110,8 +1110,7 @@
// The substatement in a selection-statement (each substatement, in the else
// form of the if statement) implicitly defines a local scope.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXX && Tok.isNot(tok::l_brace));
+ ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
ElseStmt = ParseStatement();
@@ -1175,7 +1174,7 @@
// while, for, and switch statements are local to the if, while, for, or
// switch statement (including the controlled statement).
//
- unsigned ScopeFlags = Scope::BreakScope | Scope::SwitchScope;
+ unsigned ScopeFlags = Scope::SwitchScope;
if (C99orCXX)
ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
ParseScope SwitchScope(this, ScopeFlags);
@@ -1213,8 +1212,8 @@
// See comments in ParseIfStatement for why we create a scope for the
// condition and a new scope for substatement in C++.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXX && Tok.isNot(tok::l_brace));
+ getCurScope()->AddFlags(Scope::BreakScope);
+ ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
// Read the body statement.
StmtResult Body(ParseStatement(TrailingElseLoc));
@@ -1280,7 +1279,7 @@
FullExprArg FullCond(Actions.MakeFullExpr(Cond.get(), WhileLoc));
- // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
+ // C99 6.8.5p5 - In C99, the body of the while statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
// if the body isn't a compound statement to avoid push/pop in common cases.
//
@@ -1291,8 +1290,7 @@
// See comments in ParseIfStatement for why we create a scope for the
// condition and a new scope for substatement in C++.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXX && Tok.isNot(tok::l_brace));
+ ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
// Read the body statement.
StmtResult Body(ParseStatement(TrailingElseLoc));
@@ -1325,7 +1323,7 @@
ParseScope DoScope(this, ScopeFlags);
- // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
+ // C99 6.8.5p5 - In C99, the body of the do statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
// if the body isn't a compound statement to avoid push/pop in common cases.
//
@@ -1333,9 +1331,8 @@
// The substatement in an iteration-statement implicitly defines a local scope
// which is entered and exited each time through the loop.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- (getLangOpts().C99 || getLangOpts().CPlusPlus) &&
- Tok.isNot(tok::l_brace));
+ bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
+ ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
// Read the body statement.
StmtResult Body(ParseStatement());
@@ -1346,7 +1343,7 @@
if (Tok.isNot(tok::kw_while)) {
if (!Body.isInvalid()) {
Diag(Tok, diag::err_expected_while);
- Diag(DoLoc, diag::note_matching) << "do";
+ Diag(DoLoc, diag::note_matching) << "'do'";
SkipUntil(tok::semi, StopBeforeMatch);
}
return StmtError();
@@ -1424,12 +1421,9 @@
// Names declared in the for-init-statement are in the same declarative-region
// as those declared in the condition.
//
- unsigned ScopeFlags;
+ unsigned ScopeFlags = 0;
if (C99orCXXorObjC)
- ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
- Scope::DeclScope | Scope::ControlScope;
- else
- ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
+ ScopeFlags = Scope::DeclScope | Scope::ControlScope;
ParseScope ForScope(this, ScopeFlags);
@@ -1544,6 +1538,9 @@
}
}
}
+
+ // Parse the second part of the for specifier.
+ getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
if (!ForEach && !ForRange) {
assert(!SecondPart.get() && "Shouldn't have a second expression yet.");
// Parse the second part of the for specifier.
@@ -1611,7 +1608,7 @@
T.getCloseLocation());
}
- // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
+ // C99 6.8.5p5 - In C99, the body of the for statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
// if the body isn't a compound statement to avoid push/pop in common cases.
//
@@ -1622,8 +1619,15 @@
// See comments in ParseIfStatement for why we create a scope for
// for-init-statement/condition and a new scope for substatement in C++.
//
- ParseScope InnerScope(this, Scope::DeclScope,
- C99orCXXorObjC && Tok.isNot(tok::l_brace));
+ ParseScope InnerScope(this, Scope::DeclScope, C99orCXXorObjC,
+ Tok.is(tok::l_brace));
+
+ // The body of the for loop has the same local mangling number as the
+ // for-init-statement.
+ // It will only be incremented if the body contains other things that would
+ // normally increment the mangling number (like a compound statement).
+ if (C99orCXXorObjC)
+ getCurScope()->decrementMSLocalManglingNumber();
// Read the body statement.
StmtResult Body(ParseStatement(TrailingElseLoc));
@@ -1677,7 +1681,7 @@
}
Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.take());
} else {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
return StmtError();
}
@@ -1730,8 +1734,8 @@
<< R.get()->getSourceRange();
} else
R = ParseExpression();
- if (R.isInvalid()) { // Skip to the semicolon, but don't consume it.
- SkipUntil(tok::semi, StopBeforeMatch);
+ if (R.isInvalid()) {
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
return StmtError();
}
}
@@ -1762,7 +1766,7 @@
void *LookupInlineAsmIdentifier(StringRef &LineBuf,
InlineAsmIdentifierInfo &Info,
- bool IsUnevaluatedContext) {
+ bool IsUnevaluatedContext) override {
// Collect the desired tokens.
SmallVector<Token, 16> LineToks;
const Token *FirstOrigToken = 0;
@@ -1802,7 +1806,7 @@
}
bool LookupInlineAsmField(StringRef Base, StringRef Member,
- unsigned &Offset) {
+ unsigned &Offset) override {
return TheParser.getActions().LookupInlineAsmField(Base, Member,
Offset, AsmLoc);
}
@@ -1920,30 +1924,33 @@
TemplateKWLoc,
Id);
- // If we've run into the poison token we inserted before, or there
- // was a parsing error, then claim the entire line.
- if (Invalid || Tok.is(EndOfStream)) {
- NumLineToksConsumed = LineToks.size() - 2;
-
- // Otherwise, claim up to the start of the next token.
+ // Figure out how many tokens we are into LineToks.
+ unsigned LineIndex = 0;
+ if (Tok.is(EndOfStream)) {
+ LineIndex = LineToks.size() - 2;
} else {
- // Figure out how many tokens we are into LineToks.
- unsigned LineIndex = 0;
while (LineToks[LineIndex].getLocation() != Tok.getLocation()) {
LineIndex++;
assert(LineIndex < LineToks.size() - 2); // we added two extra tokens
}
+ }
+ // If we've run into the poison token we inserted before, or there
+ // was a parsing error, then claim the entire line.
+ if (Invalid || Tok.is(EndOfStream)) {
+ NumLineToksConsumed = LineToks.size() - 2;
+ } else {
+ // Otherwise, claim up to the start of the next token.
NumLineToksConsumed = LineIndex;
}
-
- // Finally, restore the old parsing state by consuming all the
- // tokens we staged before, implicitly killing off the
- // token-lexer we pushed.
- for (unsigned n = LineToks.size() - 2 - NumLineToksConsumed; n != 0; --n) {
+
+ // Finally, restore the old parsing state by consuming all the tokens we
+ // staged before, implicitly killing off the token-lexer we pushed.
+ for (unsigned i = 0, e = LineToks.size() - LineIndex - 2; i != e; ++i) {
ConsumeAnyToken();
}
- ConsumeToken(EndOfStream);
+ assert(Tok.is(EndOfStream));
+ ConsumeToken();
// Leave LineToks in its original state.
LineToks.pop_back();
@@ -2058,7 +2065,7 @@
SourceLocation TokLoc = Tok.getLocation();
do {
// If we hit EOF, we're done, period.
- if (Tok.is(tok::eof))
+ if (isEofOrEom())
break;
if (!InAsmComment && Tok.is(tok::semi)) {
@@ -2112,12 +2119,12 @@
if (InBraces && BraceCount != savedBraceCount) {
// __asm without closing brace (this can happen at EOF).
- Diag(Tok, diag::err_expected_rbrace);
- Diag(LBraceLoc, diag::note_matching) << "{";
+ Diag(Tok, diag::err_expected) << tok::r_brace;
+ Diag(LBraceLoc, diag::note_matching) << tok::l_brace;
return StmtError();
} else if (NumTokensRead == 0) {
// Empty __asm.
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return StmtError();
}
@@ -2127,7 +2134,7 @@
SmallVector<StringRef, 4> ClobberRefs;
// We need an actual supported target.
- llvm::Triple TheTriple = Actions.Context.getTargetInfo().getTriple();
+ const llvm::Triple &TheTriple = Actions.Context.getTargetInfo().getTriple();
llvm::Triple::ArchType ArchTy = TheTriple.getArch();
const std::string &TT = TheTriple.getTriple();
const llvm::Target *TheTarget = 0;
@@ -2156,13 +2163,13 @@
if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString))
return StmtError();
- OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
- OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT));
+ std::unique_ptr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
+ std::unique_ptr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT));
// Get the instruction descriptor.
- const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
- OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
- OwningPtr<llvm::MCSubtargetInfo>
- STI(TheTarget->createMCSubtargetInfo(TT, "", ""));
+ const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
+ std::unique_ptr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
+ std::unique_ptr<llvm::MCSubtargetInfo> STI(
+ TheTarget->createMCSubtargetInfo(TT, "", ""));
llvm::SourceMgr TempSrcMgr;
llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr);
@@ -2172,11 +2179,11 @@
// Tell SrcMgr about this buffer, which is what the parser will pick up.
TempSrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
- OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
- OwningPtr<llvm::MCAsmParser>
- Parser(createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI));
- OwningPtr<llvm::MCTargetAsmParser>
- TargetParser(TheTarget->createMCAsmParser(*STI, *Parser, *MII));
+ std::unique_ptr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
+ std::unique_ptr<llvm::MCAsmParser> Parser(
+ createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI));
+ std::unique_ptr<llvm::MCTargetAsmParser> TargetParser(
+ TheTarget->createMCAsmParser(*STI, *Parser, *MII));
llvm::MCInstPrinter *IP =
TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);
@@ -2204,6 +2211,11 @@
Clobbers, MII, IP, Callback))
return StmtError();
+ // Filter out "fpsw". Clang doesn't accept it, and it always lists flags and
+ // fpsr as clobbers.
+ auto End = std::remove(Clobbers.begin(), Clobbers.end(), "fpsw");
+ Clobbers.erase(End, Clobbers.end());
+
// Build the vector of clobber StringRefs.
unsigned NumClobbers = Clobbers.size();
ClobberRefs.resize(NumClobbers);
@@ -2357,8 +2369,8 @@
Clobbers.push_back(Clobber.release());
- if (Tok.isNot(tok::comma)) break;
- ConsumeToken();
+ if (!TryConsumeToken(tok::comma))
+ break;
}
}
}
@@ -2397,7 +2409,7 @@
T.consumeOpen();
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::r_paren, StopAtSemi);
return true;
}
@@ -2434,8 +2446,8 @@
}
Exprs.push_back(Res.release());
// Eat the comma and continue parsing if it exists.
- if (Tok.isNot(tok::comma)) return false;
- ConsumeToken();
+ if (!TryConsumeToken(tok::comma))
+ return false;
}
}
@@ -2554,11 +2566,11 @@
///
/// [Borland] try-block:
/// 'try' compound-statement seh-except-block
-/// 'try' compound-statment seh-finally-block
+/// 'try' compound-statement seh-finally-block
///
StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) {
if (Tok.isNot(tok::l_brace))
- return StmtError(Diag(Tok, diag::err_expected_lbrace));
+ return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
// FIXME: Possible draft standard bug: attribute-specifier should be allowed?
StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
@@ -2629,7 +2641,7 @@
SourceLocation CatchLoc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return StmtError();
// C++ 3.3.2p3:
@@ -2662,7 +2674,7 @@
return StmtError();
if (Tok.isNot(tok::l_brace))
- return StmtError(Diag(Tok, diag::err_expected_lbrace));
+ return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
// FIXME: Possible draft standard bug: attribute-specifier should be allowed?
StmtResult Block(ParseCompoundStatement());
@@ -2683,7 +2695,7 @@
// inside these braces escaping to the surrounding code.
if (Result.Behavior == IEB_Dependent) {
if (!Tok.is(tok::l_brace)) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return;
}
@@ -2703,7 +2715,7 @@
BalancedDelimiterTracker Braces(*this, tok::l_brace);
if (Braces.consumeOpen()) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return;
}
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 076edb9..777fd01 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -101,15 +101,11 @@
do {
// Consume the 'export', if any.
SourceLocation ExportLoc;
- if (Tok.is(tok::kw_export)) {
- ExportLoc = ConsumeToken();
- }
+ TryConsumeToken(tok::kw_export, ExportLoc);
// Consume the 'template', which should be here.
SourceLocation TemplateLoc;
- if (Tok.is(tok::kw_template)) {
- TemplateLoc = ConsumeToken();
- } else {
+ if (!TryConsumeToken(tok::kw_template, TemplateLoc)) {
Diag(Tok.getLocation(), diag::err_expected_template);
return 0;
}
@@ -121,8 +117,7 @@
TemplateParams, LAngleLoc, RAngleLoc)) {
// Skip until the semi-colon or a }.
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
- if (Tok.is(tok::semi))
- ConsumeToken();
+ TryConsumeToken(tok::semi);
return 0;
}
@@ -302,11 +297,10 @@
SourceLocation &LAngleLoc,
SourceLocation &RAngleLoc) {
// Get the template parameter list.
- if (!Tok.is(tok::less)) {
+ if (!TryConsumeToken(tok::less, LAngleLoc)) {
Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
return true;
}
- LAngleLoc = ConsumeToken();
// Try to parse the template parameter list.
bool Failed = false;
@@ -322,10 +316,8 @@
Tok.setKind(tok::greater);
RAngleLoc = Tok.getLocation();
Tok.setLocation(Tok.getLocation().getLocWithOffset(1));
- } else if (Tok.is(tok::greater))
- RAngleLoc = ConsumeToken();
- else if (Failed) {
- Diag(Tok.getLocation(), diag::err_expected_greater);
+ } else if (!TryConsumeToken(tok::greater, RAngleLoc) && Failed) {
+ Diag(Tok.getLocation(), diag::err_expected) << tok::greater;
return true;
}
return false;
@@ -483,10 +475,8 @@
// Grab the ellipsis (if given).
bool Ellipsis = false;
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis)) {
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {
Ellipsis = true;
- EllipsisLoc = ConsumeToken();
-
Diag(EllipsisLoc,
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
@@ -504,7 +494,7 @@
// Unnamed template parameter. Don't have to do anything here, just
// don't consume this token.
} else {
- Diag(Tok.getLocation(), diag::err_expected_ident);
+ Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
return 0;
}
@@ -513,11 +503,9 @@
// we introduce the type parameter into the local scope.
SourceLocation EqualLoc;
ParsedType DefaultArg;
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
+ if (TryConsumeToken(tok::equal, EqualLoc))
DefaultArg = ParseTypeName(/*Range=*/0,
Declarator::TemplateTypeArgContext).get();
- }
return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, Ellipsis,
EllipsisLoc, KeyLoc, ParamName, NameLoc,
@@ -552,7 +540,7 @@
// identifier, comma, or greater. Provide a fixit if the identifier, comma,
// or greater appear immediately or after 'typename' or 'struct'. In the
// latter case, replace the keyword with 'class'.
- if (!Tok.is(tok::kw_class)) {
+ if (!TryConsumeToken(tok::kw_class)) {
bool Replace = Tok.is(tok::kw_typename) || Tok.is(tok::kw_struct);
const Token& Next = Replace ? NextToken() : Tok;
if (Next.is(tok::identifier) || Next.is(tok::comma) ||
@@ -566,19 +554,15 @@
if (Replace)
ConsumeToken();
- } else
- ConsumeToken();
+ }
// Parse the ellipsis, if given.
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis)) {
- EllipsisLoc = ConsumeToken();
-
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
Diag(EllipsisLoc,
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
: diag::ext_variadic_templates);
- }
// Get the identifier, if given.
SourceLocation NameLoc;
@@ -591,7 +575,7 @@
// Unnamed template parameter. Don't have to do anything here, just
// don't consume this token.
} else {
- Diag(Tok.getLocation(), diag::err_expected_ident);
+ Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
return 0;
}
@@ -607,8 +591,7 @@
// we introduce the template parameter into the local scope.
SourceLocation EqualLoc;
ParsedTemplateArgument DefaultArg;
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
+ if (TryConsumeToken(tok::equal, EqualLoc)) {
DefaultArg = ParseTemplateTemplateArgument();
if (DefaultArg.isInvalid()) {
Diag(Tok.getLocation(),
@@ -651,9 +634,7 @@
// we introduce the template parameter into the local scope.
SourceLocation EqualLoc;
ExprResult DefaultArg;
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
-
+ if (TryConsumeToken(tok::equal, EqualLoc)) {
// C++ [temp.param]p15:
// When parsing a default template-argument for a non-type
// template-parameter, the first non-nested > is taken as the
@@ -692,7 +673,7 @@
switch (Tok.getKind()) {
default:
- Diag(Tok.getLocation(), diag::err_expected_greater);
+ Diag(Tok.getLocation(), diag::err_expected) << tok::greater;
return true;
case tok::greater:
@@ -900,8 +881,7 @@
if (Invalid) {
// If we failed to parse the template ID but skipped ahead to a >, we're not
// going to be able to form a token annotation. Eat the '>' if present.
- if (Tok.is(tok::greater))
- ConsumeToken();
+ TryConsumeToken(tok::greater);
return true;
}
@@ -916,8 +896,7 @@
if (Type.isInvalid()) {
// If we failed to parse the template ID but skipped ahead to a >, we're not
// going to be able to form a token annotation. Eat the '>' if present.
- if (Tok.is(tok::greater))
- ConsumeToken();
+ TryConsumeToken(tok::greater);
return true;
}
@@ -1044,11 +1023,9 @@
UnqualifiedId Name;
Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken(); // the identifier
-
- // Parse the ellipsis.
- if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
-
+
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
+
// If the next token signals the end of a template argument,
// then we have a dependent template name that could be a template
// template argument.
@@ -1067,10 +1044,8 @@
UnqualifiedId Name;
Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken(); // the identifier
-
- // Parse the ellipsis.
- if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
+
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
if (isEndOfTemplateArgument(Tok)) {
bool MemberOfUnknownSpecialization;
@@ -1161,9 +1136,8 @@
}
// '<'
- if (!Tok.is(tok::less))
+ if (!TryConsumeToken(tok::less))
return false;
- ConsumeToken();
// An empty template argument list.
if (Tok.is(tok::greater))
@@ -1188,12 +1162,11 @@
// Template argument lists are constant-evaluation contexts.
EnterExpressionEvaluationContext EvalContext(Actions,Sema::ConstantEvaluated);
- while (true) {
+ do {
ParsedTemplateArgument Arg = ParseTemplateArgument();
- if (Tok.is(tok::ellipsis)) {
- SourceLocation EllipsisLoc = ConsumeToken();
+ SourceLocation EllipsisLoc;
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc);
- }
if (Arg.isInvalid()) {
SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);
@@ -1205,11 +1178,7 @@
// If the next token is a comma, consume it and keep reading
// arguments.
- if (Tok.isNot(tok::comma)) break;
-
- // Consume the comma.
- ConsumeToken();
- }
+ } while (TryConsumeToken(tok::comma));
return false;
}
@@ -1258,9 +1227,7 @@
return;
// Get the FunctionDecl.
- FunctionTemplateDecl *FunTmplD = dyn_cast<FunctionTemplateDecl>(LPT.D);
- FunctionDecl *FunD =
- FunTmplD ? FunTmplD->getTemplatedDecl() : cast<FunctionDecl>(LPT.D);
+ FunctionDecl *FunD = LPT.D->getAsFunction();
// Track template parameter depth.
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
@@ -1304,9 +1271,11 @@
new ParseScope(this, Scope::TemplateParamScope));
DeclaratorDecl *Declarator = dyn_cast<DeclaratorDecl>(FunD);
- if (Declarator && Declarator->getNumTemplateParameterLists() != 0) {
+ const unsigned DeclaratorNumTemplateParameterLists =
+ (Declarator ? Declarator->getNumTemplateParameterLists() : 0);
+ if (Declarator && DeclaratorNumTemplateParameterLists != 0) {
Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
- ++CurTemplateDepthTracker;
+ CurTemplateDepthTracker.addDepth(DeclaratorNumTemplateParameterLists);
}
Actions.ActOnReenterTemplateScope(getCurScope(), LPT.D);
++CurTemplateDepthTracker;
@@ -1341,8 +1310,10 @@
Actions.ActOnDefaultCtorInitializers(LPT.D);
if (Tok.is(tok::l_brace)) {
- assert((!FunTmplD || FunTmplD->getTemplateParameters()->getDepth() <
- TemplateParameterDepth) &&
+ assert((!isa<FunctionTemplateDecl>(LPT.D) ||
+ cast<FunctionTemplateDecl>(LPT.D)
+ ->getTemplateParameters()
+ ->getDepth() < TemplateParameterDepth) &&
"TemplateParameterDepth should be greater than the depth of "
"current template being instantiated!");
ParseFunctionStatementBody(LPT.D, FnScope);
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index a1d6b13..330e541 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -320,9 +320,8 @@
return TPResult::True();
}
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
- ConsumeToken(); // the comma.
}
return TPResult::Ambiguous();
@@ -595,13 +594,10 @@
}
}
- if (Tok.is(tok::ellipsis))
- ConsumeToken();
+ TryConsumeToken(tok::ellipsis);
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
-
- ConsumeToken();
}
// An attribute must end ']]'.
@@ -935,7 +931,6 @@
case tok::kw___alignof:
case tok::kw___builtin_choose_expr:
case tok::kw___builtin_offsetof:
- case tok::kw___builtin_types_compatible_p:
case tok::kw___builtin_va_arg:
case tok::kw___imag:
case tok::kw___real:
@@ -943,33 +938,10 @@
case tok::kw___FUNCDNAME__:
case tok::kw_L__FUNCTION__:
case tok::kw___PRETTY_FUNCTION__:
- case tok::kw___has_nothrow_assign:
- case tok::kw___has_nothrow_copy:
- case tok::kw___has_nothrow_constructor:
- case tok::kw___has_trivial_assign:
- case tok::kw___has_trivial_copy:
- case tok::kw___has_trivial_constructor:
- case tok::kw___has_trivial_destructor:
- case tok::kw___has_virtual_destructor:
- case tok::kw___is_abstract:
- case tok::kw___is_base_of:
- case tok::kw___is_class:
- case tok::kw___is_convertible_to:
- case tok::kw___is_empty:
- case tok::kw___is_enum:
- case tok::kw___is_interface_class:
- case tok::kw___is_final:
- case tok::kw___is_literal:
- case tok::kw___is_literal_type:
- case tok::kw___is_pod:
- case tok::kw___is_polymorphic:
- case tok::kw___is_sealed:
- case tok::kw___is_trivial:
- case tok::kw___is_trivially_assignable:
- case tok::kw___is_trivially_constructible:
- case tok::kw___is_trivially_copyable:
- case tok::kw___is_union:
case tok::kw___uuidof:
+#define TYPE_TRAIT(N,Spelling,K) \
+ case tok::kw_##Spelling:
+#include "clang/Basic/TokenKinds.def"
return TPResult::True();
// Obviously starts a type-specifier-seq:
@@ -1015,14 +987,6 @@
case tok::kw___vector:
case tok::kw___pixel:
case tok::kw__Atomic:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t:
- case tok::kw_sampler_t:
- case tok::kw_event_t:
case tok::kw___unknown_anytype:
return TPResult::False();
@@ -1756,9 +1720,8 @@
return TPResult::False();
}
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
- ConsumeToken(); // the comma.
}
return TPResult::Ambiguous();
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 457dd36..9936a5a 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -12,9 +12,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/Parser.h"
-#include "ParsePragma.h"
#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
@@ -33,7 +33,7 @@
public:
explicit ActionCommentHandler(Sema &S) : S(S) { }
- virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) {
+ bool HandleComment(Preprocessor &PP, SourceRange Comment) override {
S.ActOnComment(Comment);
return false;
}
@@ -63,51 +63,7 @@
// Add #pragma handlers. These are removed and destroyed in the
// destructor.
- AlignHandler.reset(new PragmaAlignHandler());
- PP.AddPragmaHandler(AlignHandler.get());
-
- GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
- PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
-
- OptionsHandler.reset(new PragmaOptionsHandler());
- PP.AddPragmaHandler(OptionsHandler.get());
-
- PackHandler.reset(new PragmaPackHandler());
- PP.AddPragmaHandler(PackHandler.get());
-
- MSStructHandler.reset(new PragmaMSStructHandler());
- PP.AddPragmaHandler(MSStructHandler.get());
-
- UnusedHandler.reset(new PragmaUnusedHandler());
- PP.AddPragmaHandler(UnusedHandler.get());
-
- WeakHandler.reset(new PragmaWeakHandler());
- PP.AddPragmaHandler(WeakHandler.get());
-
- RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
- PP.AddPragmaHandler(RedefineExtnameHandler.get());
-
- FPContractHandler.reset(new PragmaFPContractHandler());
- PP.AddPragmaHandler("STDC", FPContractHandler.get());
-
- if (getLangOpts().OpenCL) {
- OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
- PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
-
- PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
- }
- if (getLangOpts().OpenMP)
- OpenMPHandler.reset(new PragmaOpenMPHandler());
- else
- OpenMPHandler.reset(new PragmaNoOpenMPHandler());
- PP.AddPragmaHandler(OpenMPHandler.get());
-
- if (getLangOpts().MicrosoftExt) {
- MSCommentHandler.reset(new PragmaCommentHandler(actions));
- PP.AddPragmaHandler(MSCommentHandler.get());
- MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(actions));
- PP.AddPragmaHandler(MSDetectMismatchHandler.get());
- }
+ initializePragmaHandlers();
CommentSemaHandler.reset(new ActionCommentHandler(actions));
PP.addCommentHandler(CommentSemaHandler.get());
@@ -152,14 +108,8 @@
}
}
-/// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
-/// input. If so, it is consumed and false is returned.
-///
-/// If the input is malformed, this emits the specified diagnostic. Next, if
-/// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is
-/// returned.
bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
- const char *Msg, tok::TokenKind SkipToTok) {
+ const char *Msg) {
if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) {
ConsumeAnyToken();
return false;
@@ -168,35 +118,48 @@
// Detect common single-character typos and resume.
if (IsCommonTypo(ExpectedTok, Tok)) {
SourceLocation Loc = Tok.getLocation();
- Diag(Loc, DiagID)
- << Msg
- << FixItHint::CreateReplacement(SourceRange(Loc),
- getTokenSimpleSpelling(ExpectedTok));
- ConsumeAnyToken();
+ {
+ DiagnosticBuilder DB = Diag(Loc, DiagID);
+ DB << FixItHint::CreateReplacement(
+ SourceRange(Loc), tok::getPunctuatorSpelling(ExpectedTok));
+ if (DiagID == diag::err_expected)
+ DB << ExpectedTok;
+ else if (DiagID == diag::err_expected_after)
+ DB << Msg << ExpectedTok;
+ else
+ DB << Msg;
+ }
// Pretend there wasn't a problem.
+ ConsumeAnyToken();
return false;
}
- const char *Spelling = 0;
SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
- if (EndLoc.isValid() &&
- (Spelling = tok::getTokenSimpleSpelling(ExpectedTok))) {
- // Show what code to insert to fix this problem.
- Diag(EndLoc, DiagID)
- << Msg
- << FixItHint::CreateInsertion(EndLoc, Spelling);
- } else
- Diag(Tok, DiagID) << Msg;
+ const char *Spelling = 0;
+ if (EndLoc.isValid())
+ Spelling = tok::getPunctuatorSpelling(ExpectedTok);
- if (SkipToTok != tok::unknown)
- SkipUntil(SkipToTok, StopAtSemi);
+ DiagnosticBuilder DB =
+ Spelling
+ ? Diag(EndLoc, DiagID) << FixItHint::CreateInsertion(EndLoc, Spelling)
+ : Diag(Tok, DiagID);
+ if (DiagID == diag::err_expected)
+ DB << ExpectedTok;
+ else if (DiagID == diag::err_expected_after)
+ DB << Msg << ExpectedTok;
+ else
+ DB << Msg;
+
return true;
}
bool Parser::ExpectAndConsumeSemi(unsigned DiagID) {
- if (Tok.is(tok::semi) || Tok.is(tok::code_completion)) {
- ConsumeToken();
+ if (TryConsumeToken(tok::semi))
+ return false;
+
+ if (Tok.is(tok::code_completion)) {
+ handleUnexpectedCodeCompletionToken();
return false;
}
@@ -241,7 +204,8 @@
if (Kind != AfterMemberFunctionDefinition || HadMultipleSemis)
Diag(StartLoc, diag::ext_extra_semi)
- << Kind << DeclSpec::getSpecifierName((DeclSpec::TST)TST)
+ << Kind << DeclSpec::getSpecifierName((DeclSpec::TST)TST,
+ Actions.getASTContext().getPrintingPolicy())
<< FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc));
else
// A single semicolon is valid after a member function definition.
@@ -288,7 +252,7 @@
if (Toks.size() == 1 && Toks[0] == tok::eof &&
!HasFlagsSet(Flags, StopAtSemi) &&
!HasFlagsSet(Flags, StopAtCodeCompletion)) {
- while (Tok.getKind() != tok::eof)
+ while (Tok.isNot(tok::eof))
ConsumeAnyToken();
return true;
}
@@ -297,10 +261,20 @@
case tok::eof:
// Ran out of tokens.
return false;
-
+
+ case tok::annot_pragma_openmp_end:
+ // Stop before an OpenMP pragma boundary.
+ case tok::annot_module_begin:
+ case tok::annot_module_end:
+ case tok::annot_module_include:
+ // Stop before we change submodules. They generally indicate a "good"
+ // place to pick up parsing again (except in the special case where
+ // we're trying to skip to EOF).
+ return false;
+
case tok::code_completion:
if (!HasFlagsSet(Flags, StopAtCodeCompletion))
- ConsumeToken();
+ handleUnexpectedCodeCompletionToken();
return false;
case tok::l_paren:
@@ -435,41 +409,7 @@
for (unsigned i = 0, e = NumCachedScopes; i != e; ++i)
delete ScopeCache[i];
- // Remove the pragma handlers we installed.
- PP.RemovePragmaHandler(AlignHandler.get());
- AlignHandler.reset();
- PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
- GCCVisibilityHandler.reset();
- PP.RemovePragmaHandler(OptionsHandler.get());
- OptionsHandler.reset();
- PP.RemovePragmaHandler(PackHandler.get());
- PackHandler.reset();
- PP.RemovePragmaHandler(MSStructHandler.get());
- MSStructHandler.reset();
- PP.RemovePragmaHandler(UnusedHandler.get());
- UnusedHandler.reset();
- PP.RemovePragmaHandler(WeakHandler.get());
- WeakHandler.reset();
- PP.RemovePragmaHandler(RedefineExtnameHandler.get());
- RedefineExtnameHandler.reset();
-
- if (getLangOpts().OpenCL) {
- PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
- OpenCLExtensionHandler.reset();
- PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
- }
- PP.RemovePragmaHandler(OpenMPHandler.get());
- OpenMPHandler.reset();
-
- if (getLangOpts().MicrosoftExt) {
- PP.RemovePragmaHandler(MSCommentHandler.get());
- MSCommentHandler.reset();
- PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
- MSDetectMismatchHandler.reset();
- }
-
- PP.RemovePragmaHandler("STDC", FPContractHandler.get());
- FPContractHandler.reset();
+ resetPragmaHandlers();
PP.removeCommentHandler(CommentSemaHandler.get());
@@ -574,7 +514,7 @@
bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds);
- // Skip over the EOF token, flagging end of previous input for incremental
+ // Skip over the EOF token, flagging end of previous input for incremental
// processing
if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof))
ConsumeToken();
@@ -592,6 +532,12 @@
ConsumeToken();
return false;
+ case tok::annot_module_begin:
+ case tok::annot_module_end:
+ // FIXME: Update visibility based on the submodule we're in.
+ ConsumeToken();
+ return false;
+
case tok::eof:
// Late template parsing can begin.
if (getLangOpts().DelayedTemplateParsing)
@@ -679,6 +625,12 @@
case tok::annot_pragma_openmp:
ParseOpenMPDeclarativeDirective();
return DeclGroupPtrTy();
+ case tok::annot_pragma_ms_pointers_to_members:
+ HandlePragmaMSPointersToMembers();
+ return DeclGroupPtrTy();
+ case tok::annot_pragma_ms_vtordisp:
+ HandlePragmaMSVtorDisp();
+ return DeclGroupPtrTy();
case tok::semi:
// Either a C++11 empty-declaration or attribute-declaration.
SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(),
@@ -706,7 +658,7 @@
SourceLocation EndLoc;
ExprResult Result(ParseSimpleAsm(&EndLoc));
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+ ExpectAndConsume(tok::semi, diag::err_expected_after,
"top-level asm block");
if (Result.isInvalid())
@@ -793,7 +745,6 @@
ParseExplicitInstantiation(Declarator::FileContext,
ExternLoc, TemplateLoc, DeclEnd));
}
- // FIXME: Detect C++ linkage specifications here?
goto dont_know;
case tok::kw___if_exists:
@@ -909,7 +860,8 @@
const char *PrevSpec = 0;
unsigned DiagID;
- if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID))
+ if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID,
+ Actions.getASTContext().getPrintingPolicy()))
Diag(AtLoc, DiagID) << PrevSpec;
if (Tok.isObjCAtKeyword(tok::objc_protocol))
@@ -922,7 +874,7 @@
// If the declspec consisted only of 'extern' and we have a string
// literal following it, this must be a C++ linkage specifier like
// 'extern "C"'.
- if (Tok.is(tok::string_literal) && getLangOpts().CPlusPlus &&
+ if (getLangOpts().CPlusPlus && isTokenStringLiteral() &&
DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
Decl *TheDecl = ParseLinkage(DS, Declarator::FileContext);
@@ -949,26 +901,6 @@
}
}
-
-static inline bool isFunctionDeclaratorRequiringReturnTypeDeduction(
- const Declarator &D) {
- if (!D.isFunctionDeclarator() || !D.getDeclSpec().containsPlaceholderType())
- return false;
- for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
- unsigned chunkIndex = E - I - 1;
- const DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
- if (DeclType.Kind == DeclaratorChunk::Function) {
- const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- if (!FTI.hasTrailingReturnType())
- return true;
- QualType TrailingRetType = FTI.getTrailingReturnType().get();
- return TrailingRetType->getCanonicalTypeInternal()
- ->getContainedAutoType();
- }
- }
- return false;
-}
-
/// ParseFunctionDefinition - We parsed and verified that the specified
/// Declarator is well formed. If this is a K&R-style function, read the
/// parameters declaration-list, then start the compound-statement.
@@ -996,9 +928,11 @@
if (getLangOpts().ImplicitInt && D.getDeclSpec().isEmpty()) {
const char *PrevSpec;
unsigned DiagID;
+ const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
D.getMutableDeclSpec().SetTypeSpecType(DeclSpec::TST_int,
D.getIdentifierLoc(),
- PrevSpec, DiagID);
+ PrevSpec, DiagID,
+ Policy);
D.SetRangeBegin(D.getDeclSpec().getSourceRange().getBegin());
}
@@ -1029,10 +963,10 @@
if (Tok.isNot(tok::equal)) {
AttributeList *DtorAttrs = D.getAttributes();
while (DtorAttrs) {
- if (!IsThreadSafetyAttribute(DtorAttrs->getName()->getName()) &&
+ if (DtorAttrs->isKnownToGCC() &&
!DtorAttrs->isCXX11Attribute()) {
Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition)
- << DtorAttrs->getName()->getName();
+ << DtorAttrs->getName();
}
DtorAttrs = DtorAttrs->getNext();
}
@@ -1042,8 +976,7 @@
// tokens and store them for late parsing at the end of the translation unit.
if (getLangOpts().DelayedTemplateParsing && Tok.isNot(tok::equal) &&
TemplateInfo.Kind == ParsedTemplateInfo::Template &&
- !D.getDeclSpec().isConstexprSpecified() &&
- !isFunctionDeclaratorRequiringReturnTypeDeduction(D)) {
+ Actions.canDelayFunctionBody(D)) {
MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams);
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
@@ -1059,12 +992,7 @@
LexTemplateFunctionForLateParsing(Toks);
if (DP) {
- FunctionDecl *FnD = 0;
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(DP))
- FnD = FunTmpl->getTemplatedDecl();
- else
- FnD = cast<FunctionDecl>(DP);
-
+ FunctionDecl *FnD = DP->getAsFunction();
Actions.CheckForFunctionRedefinition(FnD);
Actions.MarkAsLateParsedTemplate(FnD, DP, Toks);
}
@@ -1077,7 +1005,7 @@
Actions.CurContext->isTranslationUnit()) {
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
Scope *ParentScope = getCurScope()->getParent();
-
+
D.setFunctionDefinitionKind(FDK_Definition);
Decl *FuncDecl = Actions.HandleDeclarator(ParentScope, D,
MultiTemplateParamsArg());
@@ -1089,8 +1017,9 @@
CurParsedObjCImpl->HasCFunction = true;
return FuncDecl;
}
+ // FIXME: Should we really fall through here?
}
-
+
// Enter a scope for the function body.
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
@@ -1108,28 +1037,22 @@
// safe because we're always the sole owner.
D.getMutableDeclSpec().abort();
- if (Tok.is(tok::equal)) {
+ if (TryConsumeToken(tok::equal)) {
assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='");
- ConsumeToken();
-
Actions.ActOnFinishFunctionBody(Res, 0, false);
bool Delete = false;
SourceLocation KWLoc;
- if (Tok.is(tok::kw_delete)) {
- Diag(Tok, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_deleted_function :
- diag::ext_deleted_function);
-
- KWLoc = ConsumeToken();
+ if (TryConsumeToken(tok::kw_delete, KWLoc)) {
+ Diag(KWLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_deleted_function
+ : diag::ext_deleted_function);
Actions.SetDeclDeleted(Res, KWLoc);
Delete = true;
- } else if (Tok.is(tok::kw_default)) {
- Diag(Tok, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_defaulted_function :
- diag::ext_defaulted_function);
-
- KWLoc = ConsumeToken();
+ } else if (TryConsumeToken(tok::kw_default, KWLoc)) {
+ Diag(KWLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_defaulted_function
+ : diag::ext_defaulted_function);
Actions.SetDeclDefaulted(Res, KWLoc);
} else {
llvm_unreachable("function definition after = not 'delete' or 'default'");
@@ -1139,9 +1062,9 @@
Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)
<< Delete;
SkipUntil(tok::semi);
- } else {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- Delete ? "delete" : "default", tok::semi);
+ } else if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ Delete ? "delete" : "default")) {
+ SkipUntil(tok::semi);
}
return Res;
@@ -1195,9 +1118,8 @@
// NOTE: GCC just makes this an ext-warn. It's not clear what it does with
// the declarations though. It's trivial to ignore them, really hard to do
// anything else with them.
- if (Tok.is(tok::semi)) {
+ if (TryConsumeToken(tok::semi)) {
Diag(DSStart, diag::err_declaration_does_not_declare_param);
- ConsumeToken();
continue;
}
@@ -1237,20 +1159,20 @@
for (unsigned i = 0; ; ++i) {
// C99 6.9.1p6: those declarators shall declare only identifiers from
// the identifier list.
- if (i == FTI.NumArgs) {
+ if (i == FTI.NumParams) {
Diag(ParmDeclarator.getIdentifierLoc(), diag::err_no_matching_param)
<< ParmDeclarator.getIdentifier();
break;
}
- if (FTI.ArgInfo[i].Ident == ParmDeclarator.getIdentifier()) {
+ if (FTI.Params[i].Ident == ParmDeclarator.getIdentifier()) {
// Reject redefinitions of parameters.
- if (FTI.ArgInfo[i].Param) {
+ if (FTI.Params[i].Param) {
Diag(ParmDeclarator.getIdentifierLoc(),
diag::err_param_redefinition)
<< ParmDeclarator.getIdentifier();
} else {
- FTI.ArgInfo[i].Param = Param;
+ FTI.Params[i].Param = Param;
}
break;
}
@@ -1271,12 +1193,14 @@
ParseDeclarator(ParmDeclarator);
}
- if (ExpectAndConsumeSemi(diag::err_expected_semi_declaration)) {
- // Skip to end of block or statement
- SkipUntil(tok::semi);
- if (Tok.is(tok::semi))
- ConsumeToken();
- }
+ // Consume ';' and continue parsing.
+ if (!ExpectAndConsumeSemi(diag::err_expected_semi_declaration))
+ continue;
+
+ // Otherwise recover by skipping to next semi or mandatory function body.
+ if (SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch))
+ break;
+ TryConsumeToken(tok::semi);
}
// The actions module must verify that all arguments were declared.
@@ -1340,16 +1264,15 @@
ExprResult Result(ParseAsmStringLiteral());
- if (Result.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
- if (EndLoc)
- *EndLoc = Tok.getLocation();
- ConsumeAnyToken();
- } else {
+ if (!Result.isInvalid()) {
// Close the paren and get the location of the end bracket
T.consumeClose();
if (EndLoc)
*EndLoc = T.getCloseLocation();
+ } else if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) {
+ if (EndLoc)
+ *EndLoc = Tok.getLocation();
+ ConsumeParen();
}
return Result;
@@ -1430,8 +1353,8 @@
// Look up and classify the identifier. We don't perform any typo-correction
// after a scope specifier, because in general we can't recover from typos
- // there (eg, after correcting 'A::tempalte B<X>::C', we would need to jump
- // back into scope specifier parsing).
+ // there (eg, after correcting 'A::tempalte B<X>::C' [sic], we would need to
+ // jump back into scope specifier parsing).
Sema::NameClassification Classification
= Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next,
IsAddressOfOperand, SS.isEmpty() ? CCC : 0);
@@ -1504,16 +1427,34 @@
}
bool Parser::TryKeywordIdentFallback(bool DisableKeyword) {
- assert(Tok.isNot(tok::identifier));
+ assert(!Tok.is(tok::identifier) && !Tok.isAnnotation());
Diag(Tok, diag::ext_keyword_as_ident)
<< PP.getSpelling(Tok)
<< DisableKeyword;
- if (DisableKeyword)
- Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();
+ if (DisableKeyword) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ ContextualKeywords[II] = Tok.getKind();
+ II->RevertTokenIDToIdentifier();
+ }
Tok.setKind(tok::identifier);
return true;
}
+bool Parser::TryIdentKeywordUpgrade() {
+ assert(Tok.is(tok::identifier));
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ assert(II->hasRevertedTokenIDToIdentifier());
+ // If we find that this is in fact the name of a type trait,
+ // update the token kind in place and parse again to treat it as
+ // the appropriate kind of type trait.
+ llvm::SmallDenseMap<const IdentifierInfo *, tok::TokenKind>::iterator Known =
+ ContextualKeywords.find(II);
+ if (Known == ContextualKeywords.end())
+ return false;
+ Tok.setKind(Known->second);
+ return true;
+}
+
/// TryAnnotateTypeOrScopeToken - If the current token position is on a
/// typename (possibly qualified in C++) or a C++ scope specifier not followed
/// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens
@@ -1549,7 +1490,7 @@
// We will consume the typedef token here and put it back after we have
// parsed the first identifier, transforming it into something more like:
// typename T_::D typedef D;
- if (getLangOpts().MicrosoftMode && NextToken().is(tok::kw_typedef)) {
+ if (getLangOpts().MSVCCompat && NextToken().is(tok::kw_typedef)) {
Token TypedefToken;
PP.Lex(TypedefToken);
bool Result = TryAnnotateTypeOrScopeToken(EnteringContext, NeedType);
@@ -1601,7 +1542,8 @@
Tok.getLocation());
} else if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
- if (TemplateId->Kind == TNK_Function_template) {
+ if (TemplateId->Kind != TNK_Type_template &&
+ TemplateId->Kind != TNK_Dependent_template_name) {
Diag(Tok, diag::err_typename_refers_to_non_type_template)
<< Tok.getAnnotationRange();
return true;
@@ -1725,8 +1667,7 @@
// annotation token to a type annotation token now.
AnnotateTemplateIdTokenAsType();
return false;
- } else if (TemplateId->Kind == TNK_Var_template)
- return false;
+ }
}
if (SS.isEmpty())
@@ -1780,8 +1721,8 @@
case tok::pipeequal: // |=
case tok::equalequal: // ==
Diag(Tok, diag::err_invalid_token_after_declarator_suggest_equal)
- << getTokenSimpleSpelling(Kind)
- << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "=");
+ << Kind
+ << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "=");
case tok::equal:
return true;
}
@@ -1910,7 +1851,7 @@
BalancedDelimiterTracker Braces(*this, tok::l_brace);
if (Braces.consumeOpen()) {
- Diag(Tok, diag::err_expected_lbrace);
+ Diag(Tok, diag::err_expected) << tok::l_brace;
return;
}
@@ -1928,14 +1869,15 @@
}
// Parse the declarations.
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ // FIXME: Support module import within __if_exists?
+ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
MaybeParseMicrosoftAttributes(attrs);
DeclGroupPtrTy Result = ParseExternalDeclaration(attrs);
if (Result && !getCurScope()->getParent())
Actions.getASTConsumer().HandleTopLevelDecl(Result.get());
- }
+ }
Braces.consumeClose();
}
@@ -1991,17 +1933,20 @@
P.Diag(P.Tok, diag::err_bracket_depth_exceeded)
<< P.getLangOpts().BracketDepth;
P.Diag(P.Tok, diag::note_bracket_depth);
- P.SkipUntil(tok::eof);
- return true;
+ P.cutOffParsing();
+ return true;
}
bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID,
- const char *Msg,
- tok::TokenKind SkipToToc ) {
+ const char *Msg,
+ tok::TokenKind SkipToTok) {
LOpen = P.Tok.getLocation();
- if (P.ExpectAndConsume(Kind, DiagID, Msg, SkipToToc))
+ if (P.ExpectAndConsume(Kind, DiagID, Msg)) {
+ if (SkipToTok != tok::unknown)
+ P.SkipUntil(SkipToTok, Parser::StopAtSemi);
return true;
-
+ }
+
if (getDepth() < MaxDepth)
return false;
@@ -2010,17 +1955,9 @@
bool BalancedDelimiterTracker::diagnoseMissingClose() {
assert(!P.Tok.is(Close) && "Should have consumed closing delimiter");
-
- const char *LHSName = "unknown";
- diag::kind DID;
- switch (Close) {
- default: llvm_unreachable("Unexpected balanced token");
- case tok::r_paren : LHSName = "("; DID = diag::err_expected_rparen; break;
- case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break;
- case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break;
- }
- P.Diag(P.Tok, DID);
- P.Diag(LOpen, diag::note_matching) << LHSName;
+
+ P.Diag(P.Tok, diag::err_expected) << Close;
+ P.Diag(LOpen, diag::note_matching) << Kind;
// If we're not already at some kind of closing bracket, skip to our closing
// token.
diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h
index f68a2e0..711dc2a 100644
--- a/lib/Parse/RAIIObjectsForParser.h
+++ b/lib/Parse/RAIIObjectsForParser.h
@@ -415,8 +415,8 @@
return diagnoseOverflow();
}
-
- bool expectAndConsume(unsigned DiagID,
+
+ bool expectAndConsume(unsigned DiagID = diag::err_expected,
const char *Msg = "",
tok::TokenKind SkipToTok = tok::unknown);
bool consumeClose() {