aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:02:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:02:28 +0000
commit7442d6faa2719e4e7d33a7021c406c5a4facd74d (patch)
treec72b9241553fc9966179aba84f90f17bfa9235c3 /lib/Parse
parentb52119637f743680a99710ce5fdb6646da2772af (diff)
downloadsrc-7442d6faa2719e4e7d33a7021c406c5a4facd74d.tar.gz
src-7442d6faa2719e4e7d33a7021c406c5a4facd74d.zip
Vendor import of clang trunk r300422:vendor/clang/clang-trunk-r300422
Notes
Notes: svn path=/vendor/clang/dist/; revision=317019 svn path=/vendor/clang/clang-trunk-r300422/; revision=317020; tag=vendor/clang/clang-trunk-r300422
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp8
-rw-r--r--lib/Parse/ParseDecl.cpp348
-rw-r--r--lib/Parse/ParseDeclCXX.cpp193
-rw-r--r--lib/Parse/ParseExpr.cpp83
-rw-r--r--lib/Parse/ParseExprCXX.cpp91
-rw-r--r--lib/Parse/ParseInit.cpp2
-rw-r--r--lib/Parse/ParseObjc.cpp101
-rw-r--r--lib/Parse/ParseOpenMP.cpp11
-rw-r--r--lib/Parse/ParsePragma.cpp153
-rw-r--r--lib/Parse/ParseStmt.cpp25
-rw-r--r--lib/Parse/ParseStmtAsm.cpp19
-rw-r--r--lib/Parse/ParseTemplate.cpp33
-rw-r--r--lib/Parse/Parser.cpp52
-rw-r--r--lib/Parse/RAIIObjectsForParser.h447
14 files changed, 782 insertions, 784 deletions
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index c52b61e7e983..172b0edce5e4 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -12,9 +12,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/Parser.h"
-#include "RAIIObjectsForParser.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Scope.h"
using namespace clang;
@@ -344,9 +344,9 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// The argument isn't actually potentially evaluated unless it is
// used.
- EnterExpressionEvaluationContext Eval(Actions,
- Sema::PotentiallyEvaluatedIfUsed,
- Param);
+ EnterExpressionEvaluationContext Eval(
+ Actions,
+ Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed, Param);
ExprResult DefArgResult;
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 2d320878014b..1465d21ac5ee 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -12,7 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/Parser.h"
-#include "RAIIObjectsForParser.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/AddressSpaces.h"
@@ -308,7 +308,9 @@ unsigned Parser::ParseAttributeArgsCommon(
do {
bool Uneval = attributeParsedArgsUnevaluated(*AttrName);
EnterExpressionEvaluationContext Unevaluated(
- Actions, Uneval ? Sema::Unevaluated : Sema::ConstantEvaluated,
+ Actions,
+ Uneval ? Sema::ExpressionEvaluationContext::Unevaluated
+ : Sema::ExpressionEvaluationContext::ConstantEvaluated,
/*LambdaContextDecl=*/nullptr,
/*IsDecltype=*/false);
@@ -356,6 +358,10 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
ScopeLoc, Syntax);
return;
+ } else if (AttrKind == AttributeList::AT_ExternalSourceSymbol) {
+ ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, Syntax);
+ return;
} else if (AttrKind == AttributeList::AT_ObjCBridgeRelated) {
ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, Syntax);
@@ -389,6 +395,25 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
ScopeLoc, Syntax);
}
+unsigned Parser::ParseClangAttributeArgs(
+ 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);
+
+ if (AttrKind == AttributeList::AT_ExternalSourceSymbol) {
+ ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, Syntax);
+ return Attrs.getList() ? Attrs.getList()->getNumArgs() : 0;
+ }
+
+ return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, Syntax);
+}
+
bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs) {
@@ -1064,6 +1089,119 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
Syntax, StrictLoc, ReplacementExpr.get());
}
+/// \brief Parse the contents of the "external_source_symbol" attribute.
+///
+/// external-source-symbol-attribute:
+/// 'external_source_symbol' '(' keyword-arg-list ')'
+///
+/// keyword-arg-list:
+/// keyword-arg
+/// keyword-arg ',' keyword-arg-list
+///
+/// keyword-arg:
+/// 'language' '=' <string>
+/// 'defined_in' '=' <string>
+/// 'generated_declaration'
+void Parser::ParseExternalSourceSymbolAttribute(
+ IdentifierInfo &ExternalSourceSymbol, SourceLocation Loc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc, AttributeList::Syntax Syntax) {
+ // Opening '('.
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.expectAndConsume())
+ return;
+
+ // Initialize the pointers for the keyword identifiers when required.
+ if (!Ident_language) {
+ Ident_language = PP.getIdentifierInfo("language");
+ Ident_defined_in = PP.getIdentifierInfo("defined_in");
+ Ident_generated_declaration = PP.getIdentifierInfo("generated_declaration");
+ }
+
+ ExprResult Language;
+ bool HasLanguage = false;
+ ExprResult DefinedInExpr;
+ bool HasDefinedIn = false;
+ IdentifierLoc *GeneratedDeclaration = nullptr;
+
+ // Parse the language/defined_in/generated_declaration keywords
+ do {
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_external_source_symbol_expected_keyword);
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+
+ SourceLocation KeywordLoc = Tok.getLocation();
+ IdentifierInfo *Keyword = Tok.getIdentifierInfo();
+ if (Keyword == Ident_generated_declaration) {
+ if (GeneratedDeclaration) {
+ Diag(Tok, diag::err_external_source_symbol_duplicate_clause) << Keyword;
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+ GeneratedDeclaration = ParseIdentifierLoc();
+ continue;
+ }
+
+ if (Keyword != Ident_language && Keyword != Ident_defined_in) {
+ Diag(Tok, diag::err_external_source_symbol_expected_keyword);
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+
+ ConsumeToken();
+ if (ExpectAndConsume(tok::equal, diag::err_expected_after,
+ Keyword->getName())) {
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+
+ bool HadLanguage = HasLanguage, HadDefinedIn = HasDefinedIn;
+ if (Keyword == Ident_language)
+ HasLanguage = true;
+ else
+ HasDefinedIn = true;
+
+ if (Tok.isNot(tok::string_literal)) {
+ Diag(Tok, diag::err_expected_string_literal)
+ << /*Source='external_source_symbol attribute'*/ 3
+ << /*language | source container*/ (Keyword != Ident_language);
+ SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);
+ continue;
+ }
+ if (Keyword == Ident_language) {
+ if (HadLanguage) {
+ Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)
+ << Keyword;
+ ParseStringLiteralExpression();
+ continue;
+ }
+ Language = ParseStringLiteralExpression();
+ } else {
+ assert(Keyword == Ident_defined_in && "Invalid clause keyword!");
+ if (HadDefinedIn) {
+ Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)
+ << Keyword;
+ ParseStringLiteralExpression();
+ continue;
+ }
+ DefinedInExpr = ParseStringLiteralExpression();
+ }
+ } while (TryConsumeToken(tok::comma));
+
+ // Closing ')'.
+ if (T.consumeClose())
+ return;
+ if (EndLoc)
+ *EndLoc = T.getCloseLocation();
+
+ ArgsUnion Args[] = {Language.get(), DefinedInExpr.get(),
+ GeneratedDeclaration};
+ Attrs.addNew(&ExternalSourceSymbol, SourceRange(Loc, T.getCloseLocation()),
+ ScopeName, ScopeLoc, Args, llvm::array_lengthof(Args), Syntax);
+}
+
/// \brief Parse the contents of the "objc_bridge_related" attribute.
/// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')'
/// related_class:
@@ -2824,44 +2962,23 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
->Kind == TNK_Type_template) {
// We have a qualified template-id, e.g., N::A<int>
- // C++ [class.qual]p2:
- // In a lookup in which the constructor is an acceptable lookup
- // result and the nested-name-specifier nominates a class C:
+ // If this would be a valid constructor declaration with template
+ // arguments, we will reject the attempt to form an invalid type-id
+ // referring to the injected-class-name when we annotate the token,
+ // per C++ [class.qual]p2.
//
- // - if the name specified after the
- // nested-name-specifier, when looked up in C, is the
- // injected-class-name of C (Clause 9), or
- //
- // - if the name specified after the nested-name-specifier
- // is the same as the identifier or the
- // simple-template-id's template-name in the last
- // component of the nested-name-specifier,
- //
- // the name is instead considered to name the constructor of
- // class C.
- //
- // Thus, if the template-name is actually the constructor
- // name, then the code is ill-formed; this interpretation is
- // reinforced by the NAD status of core issue 635.
+ // To improve diagnostics for this case, parse the declaration as a
+ // constructor (and reject the extra template arguments later).
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next);
if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
TemplateId->Name &&
- Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS)) {
- 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
- // complain about it later.
- goto DoneWithDeclSpec;
- }
-
- // The user meant this to name a type, but it actually names
- // a constructor with some extraneous template
- // arguments. Complain, then parse it as a type as the user
- // intended.
- Diag(TemplateId->TemplateNameLoc,
- diag::err_out_of_line_template_id_type_names_constructor)
- << TemplateId->Name << 0 /* template name */;
+ Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS) &&
+ 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
+ // complain about it later.
+ goto DoneWithDeclSpec;
}
DS.getTypeSpecScope() = SS;
@@ -2892,30 +3009,21 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (Next.isNot(tok::identifier))
goto DoneWithDeclSpec;
- // If we're in a context where the identifier could be a class name,
- // check whether this is a constructor declaration.
+ // Check whether this is a constructor declaration. If we're in a
+ // context where the identifier could be a class name, and it has the
+ // shape of a constructor declaration, process it as one.
if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(),
- &SS)) {
- if (isConstructorDeclarator(/*Unqualified*/false))
- goto DoneWithDeclSpec;
-
- // As noted in C++ [class.qual]p2 (cited above), when the name
- // of the class is qualified in a context where it could name
- // a constructor, its a constructor name. However, we've
- // looked at the declarator, and the user probably meant this
- // to be a type. Complain that it isn't supposed to be treated
- // as a type, then proceed to parse it as a type.
- Diag(Next.getLocation(),
- diag::err_out_of_line_template_id_type_names_constructor)
- << Next.getIdentifierInfo() << 1 /* type */;
- }
+ &SS) &&
+ isConstructorDeclarator(/*Unqualified*/ false))
+ goto DoneWithDeclSpec;
ParsedType TypeRep =
Actions.getTypeName(*Next.getIdentifierInfo(), Next.getLocation(),
getCurScope(), &SS, false, false, nullptr,
/*IsCtorOrDtorName=*/false,
- /*NonTrivialSourceInfo=*/true);
+ /*WantNonTrivialSourceInfo=*/true,
+ isClassTemplateDeductionContext(DSContext));
// If the referenced identifier is not a type, then this declspec is
// erroneous: We already checked about that it has no type specifier, and
@@ -2996,6 +3104,31 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (DS.hasTypeSpecifier())
goto DoneWithDeclSpec;
+ // If the token is an identifier named "__declspec" and Microsoft
+ // extensions are not enabled, it is likely that there will be cascading
+ // parse errors if this really is a __declspec attribute. Attempt to
+ // recognize that scenario and recover gracefully.
+ if (!getLangOpts().DeclSpecKeyword && Tok.is(tok::identifier) &&
+ Tok.getIdentifierInfo()->getName().equals("__declspec")) {
+ Diag(Loc, diag::err_ms_attributes_not_enabled);
+
+ // The next token should be an open paren. If it is, eat the entire
+ // attribute declaration and continue.
+ if (NextToken().is(tok::l_paren)) {
+ // Consume the __declspec identifier.
+ ConsumeToken();
+
+ // Eat the parens and everything between them.
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.consumeOpen()) {
+ assert(false && "Not a left paren?");
+ return;
+ }
+ T.skipToEnd();
+ continue;
+ }
+ }
+
// In C++, check to see if this is a scope specifier like foo::bar::, if
// so handle it as such. This is important for ctor parsing.
if (getLangOpts().CPlusPlus) {
@@ -3029,9 +3162,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
continue;
}
- ParsedType TypeRep =
- Actions.getTypeName(*Tok.getIdentifierInfo(),
- Tok.getLocation(), getCurScope());
+ ParsedType TypeRep = Actions.getTypeName(
+ *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), nullptr,
+ false, false, nullptr, false, false,
+ isClassTemplateDeductionContext(DSContext));
// If this is not a typedef name, don't parse it as part of the declspec,
// it must be an implicit int or an error.
@@ -3054,6 +3188,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
isConstructorDeclarator(/*Unqualified*/true))
goto DoneWithDeclSpec;
+ // Likewise, if this is a context where the identifier could be a template
+ // name, check whether this is a deduction guide declaration.
+ if (getLangOpts().CPlusPlus1z &&
+ (DSContext == DSC_class || DSContext == DSC_top_level) &&
+ Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(),
+ Tok.getLocation()) &&
+ isConstructorDeclarator(/*Unqualified*/ true,
+ /*DeductionGuide*/ true))
+ goto DoneWithDeclSpec;
+
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
DiagID, TypeRep, Policy);
if (isInvalid)
@@ -3951,8 +4095,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// anything that's a simple-type-specifier followed by '(' as an
// expression. This suffices because function types are not valid
// underlying types anyway.
- EnterExpressionEvaluationContext Unevaluated(Actions,
- Sema::ConstantEvaluated);
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
TPResult TPR = isExpressionOrTypeSpecifierSimple(NextToken().getKind());
// If the next token starts an expression, we know we're parsing a
// bit-field. This is the common case.
@@ -4673,7 +4817,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
}
}
-bool Parser::isConstructorDeclarator(bool IsUnqualified) {
+bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide) {
TentativeParsingAction TPA(*this);
// Parse the C++ scope specifier.
@@ -4694,6 +4838,10 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) {
return false;
}
+ // There may be attributes here, appertaining to the constructor name or type
+ // we just stepped past.
+ SkipCXX11Attributes();
+
// Current class name must be followed by a left parenthesis.
if (Tok.isNot(tok::l_paren)) {
TPA.Revert();
@@ -4761,13 +4909,24 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) {
case tok::r_paren:
// C(X )
- if (NextToken().is(tok::colon) || NextToken().is(tok::kw_try)) {
+
+ // Skip past the right-paren and any following attributes to get to
+ // the function body or trailing-return-type.
+ ConsumeParen();
+ SkipCXX11Attributes();
+
+ if (DeductionGuide) {
+ // C(X) -> ... is a deduction guide.
+ IsConstructor = Tok.is(tok::arrow);
+ break;
+ }
+ if (Tok.is(tok::colon) || Tok.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 (Tok.is(tok::semi) || Tok.is(tok::l_brace)) {
// If we have a constructor name within the class definition,
// assume these were meant to be constructors:
// C(X) {
@@ -4778,7 +4937,7 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) {
//
// 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
+ // a constructor name.
// currently, so we're somewhat conservative here.
IsConstructor = IsUnqualified;
}
@@ -4806,9 +4965,10 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) {
/// [ only if AttReqs & AR_CXX11AttributesParsed ]
/// Note: vendor can be GNU, MS, etc and can be explicitly controlled via
/// AttrRequirements bitmask values.
-void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs,
- bool AtomicAllowed,
- bool IdentifierRequired) {
+void Parser::ParseTypeQualifierListOpt(
+ DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed,
+ bool IdentifierRequired,
+ Optional<llvm::function_ref<void()>> CodeCompletionHandler) {
if (getLangOpts().CPlusPlus11 && (AttrReqs & AR_CXX11AttributesParsed) &&
isCXX11AttributeSpecifier()) {
ParsedAttributesWithRange attrs(AttrFactory);
@@ -4826,7 +4986,10 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs,
switch (Tok.getKind()) {
case tok::code_completion:
- Actions.CodeCompleteTypeQualifiers(DS);
+ if (CodeCompletionHandler)
+ (*CodeCompletionHandler)();
+ else
+ Actions.CodeCompleteTypeQualifiers(DS);
return cutOffParsing();
case tok::kw_const:
@@ -5309,21 +5472,29 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// We found something that indicates the start of an unqualified-id.
// Parse that unqualified-id.
bool AllowConstructorName;
- if (D.getDeclSpec().hasTypeSpecifier())
+ bool AllowDeductionGuide;
+ if (D.getDeclSpec().hasTypeSpecifier()) {
AllowConstructorName = false;
- else if (D.getCXXScopeSpec().isSet())
+ AllowDeductionGuide = false;
+ } else if (D.getCXXScopeSpec().isSet()) {
AllowConstructorName =
(D.getContext() == Declarator::FileContext ||
D.getContext() == Declarator::MemberContext);
- else
+ AllowDeductionGuide = false;
+ } else {
AllowConstructorName = (D.getContext() == Declarator::MemberContext);
+ AllowDeductionGuide =
+ (D.getContext() == Declarator::FileContext ||
+ D.getContext() == Declarator::MemberContext);
+ }
SourceLocation TemplateKWLoc;
bool HadScope = D.getCXXScopeSpec().isValid();
if (ParseUnqualifiedId(D.getCXXScopeSpec(),
/*EnteringContext=*/true,
/*AllowDestructorName=*/true, AllowConstructorName,
- nullptr, TemplateKWLoc, D.getName()) ||
+ AllowDeductionGuide, nullptr, TemplateKWLoc,
+ D.getName()) ||
// Once we're past the identifier, if the scope was bad, mark the
// whole declarator bad.
D.getCXXScopeSpec().isInvalid()) {
@@ -5409,6 +5580,21 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
if (Tok.is(tok::l_square))
return ParseMisplacedBracketDeclarator(D);
if (D.getContext() == Declarator::MemberContext) {
+ // Objective-C++: Detect C++ keywords and try to prevent further errors by
+ // treating these keyword as valid member names.
+ if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus &&
+ Tok.getIdentifierInfo() &&
+ Tok.getIdentifierInfo()->isCPlusPlusKeyword(getLangOpts())) {
+ Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_member_name_or_semi_objcxx_keyword)
+ << Tok.getIdentifierInfo()
+ << (D.getDeclSpec().isEmpty() ? SourceRange()
+ : D.getDeclSpec().getSourceRange());
+ D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ D.SetRangeEnd(Tok.getLocation());
+ ConsumeToken();
+ goto PastIdentifier;
+ }
Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
diag::err_expected_member_name_or_semi)
<< (D.getDeclSpec().isEmpty() ? SourceRange()
@@ -5744,7 +5930,11 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
// Parse cv-qualifier-seq[opt].
ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed,
- /*AtomicAllowed*/ false);
+ /*AtomicAllowed*/ false,
+ /*IdentifierRequired=*/false,
+ llvm::function_ref<void()>([&]() {
+ Actions.CodeCompleteFunctionQualifiers(DS, D);
+ }));
if (!DS.getSourceRange().getEnd().isInvalid()) {
EndLoc = DS.getSourceRange().getEnd();
ConstQualifierLoc = DS.getConstSpecLoc();
@@ -6097,9 +6287,10 @@ void Parser::ParseParameterDeclarationClause(
// The argument isn't actually potentially evaluated unless it is
// used.
- EnterExpressionEvaluationContext Eval(Actions,
- Sema::PotentiallyEvaluatedIfUsed,
- Param);
+ EnterExpressionEvaluationContext Eval(
+ Actions,
+ Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed,
+ Param);
ExprResult DefArgResult;
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
@@ -6249,8 +6440,8 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
if (getLangOpts().CPlusPlus) {
NumElements = ParseConstantExpression();
} else {
- EnterExpressionEvaluationContext Unevaluated(Actions,
- Sema::ConstantEvaluated);
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
NumElements =
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
}
@@ -6385,8 +6576,9 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
const bool hasParens = Tok.is(tok::l_paren);
- EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
- Sema::ReuseLambdaContextDecl);
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated,
+ Sema::ReuseLambdaContextDecl);
bool isCastExpr;
ParsedType CastTy;
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 3f1fe7e06fe3..b25152a3183e 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/Parser.h"
-#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/Attributes.h"
@@ -20,6 +19,7 @@
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/PrettyDeclStackTrace.h"
@@ -266,15 +266,26 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false);
+ ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false,
+ /*MayBePseudoDestructor=*/nullptr,
+ /*IsTypename=*/false,
+ /*LastII=*/nullptr,
+ /*OnlyNamespace=*/true);
- if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
+ if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_namespace_name);
// Skip to end of the definition and eat the ';'.
SkipUntil(tok::semi);
return nullptr;
}
+ if (SS.isInvalid()) {
+ // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier.
+ // Skip to end of the definition and eat the ';'.
+ SkipUntil(tok::semi);
+ return nullptr;
+ }
+
// Parse identifier.
IdentifierInfo *Ident = Tok.getIdentifierInfo();
SourceLocation IdentLoc = ConsumeToken();
@@ -487,13 +498,17 @@ Decl *Parser::ParseUsingDirective(unsigned Context,
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false);
+ ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false,
+ /*MayBePseudoDestructor=*/nullptr,
+ /*IsTypename=*/false,
+ /*LastII=*/nullptr,
+ /*OnlyNamespace=*/true);
IdentifierInfo *NamespcName = nullptr;
SourceLocation IdentLoc = SourceLocation();
// Parse namespace-name.
- if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
+ if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_namespace_name);
// If there was invalid namespace name, skip to end of decl, and eat ';'.
SkipUntil(tok::semi);
@@ -501,6 +516,13 @@ Decl *Parser::ParseUsingDirective(unsigned Context,
return nullptr;
}
+ if (SS.isInvalid()) {
+ // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier.
+ // Skip to end of the definition and eat the ';'.
+ SkipUntil(tok::semi);
+ return nullptr;
+ }
+
// Parse identifier.
NamespcName = Tok.getIdentifierInfo();
IdentLoc = ConsumeToken();
@@ -576,6 +598,7 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
/*AllowDestructorName=*/true,
/*AllowConstructorName=*/!(Tok.is(tok::identifier) &&
NextToken().is(tok::equal)),
+ /*AllowDeductionGuide=*/false,
nullptr, D.TemplateKWLoc, D.Name))
return true;
}
@@ -912,8 +935,9 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
// C++11 [dcl.type.simple]p4:
// The operand of the decltype specifier is an unevaluated operand.
- EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
- nullptr,/*IsDecltype=*/true);
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
+ /*IsDecltype=*/true);
Result =
Actions.CorrectDelayedTyposInExpr(ParseExpression(), [](Expr *E) {
return E->hasPlaceholderType() ? ExprError() : E;
@@ -1076,7 +1100,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
if (TemplateId->Kind == TNK_Type_template ||
TemplateId->Kind == TNK_Dependent_template_name) {
- AnnotateTemplateIdTokenAsType();
+ AnnotateTemplateIdTokenAsType(/*IsClassName*/true);
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
ParsedType Type = getTypeAnnotation(Tok);
@@ -1124,10 +1148,10 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
// Parse the full template-id, then turn it into a type.
if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),
- TemplateName, true))
+ TemplateName))
return true;
- if (TNK == TNK_Dependent_template_name)
- AnnotateTemplateIdTokenAsType();
+ if (TNK == TNK_Type_template || TNK == TNK_Dependent_template_name)
+ AnnotateTemplateIdTokenAsType(/*IsClassName*/true);
// If we didn't end up with a typename token, there's nothing more we
// can do.
@@ -1144,10 +1168,11 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
// We have an identifier; check whether it is actually a type.
IdentifierInfo *CorrectedII = nullptr;
- ParsedType Type =
- Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, true, false, nullptr,
- /*IsCtorOrDtorName=*/false,
- /*NonTrivialTypeSourceInfo=*/true, &CorrectedII);
+ ParsedType Type = Actions.getTypeName(
+ *Id, IdLoc, getCurScope(), &SS, /*IsClassName=*/true, false, nullptr,
+ /*IsCtorOrDtorName=*/false,
+ /*NonTrivialTypeSourceInfo=*/true,
+ /*IsClassTemplateDeductionContext*/ false, &CorrectedII);
if (!Type) {
Diag(IdLoc, diag::err_expected_class_name);
return true;
@@ -1381,6 +1406,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
!Tok.isAnnotation() &&
Tok.getIdentifierInfo() &&
Tok.isOneOf(tok::kw___is_abstract,
+ tok::kw___is_aggregate,
tok::kw___is_arithmetic,
tok::kw___is_array,
tok::kw___is_assignable,
@@ -1885,6 +1911,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
}
+ if (!TagOrTempResult.isInvalid())
+ // Delayed proccessing of attributes.
+ Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs.getList());
+
const char *PrevSpec = nullptr;
unsigned DiagID;
bool Result;
@@ -2283,7 +2313,11 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
// GNU-style and C++11 attributes are not allowed here, but they will be
// handled by the caller. Diagnose everything else.
- ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, false);
+ ParseTypeQualifierListOpt(
+ DS, AR_NoAttributesParsed, false,
+ /*IdentifierRequired=*/false, llvm::function_ref<void()>([&]() {
+ Actions.CodeCompleteFunctionQualifiers(DS, D, &VS);
+ }));
D.ExtendWithDeclSpec(DS);
if (D.isFunctionDeclarator()) {
@@ -2425,8 +2459,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Try to parse an unqualified-id.
SourceLocation TemplateKWLoc;
UnqualifiedId Name;
- if (ParseUnqualifiedId(SS, false, true, true, nullptr, TemplateKWLoc,
- Name)) {
+ if (ParseUnqualifiedId(SS, false, true, true, false, nullptr,
+ TemplateKWLoc, Name)) {
SkipUntil(tok::semi);
return nullptr;
}
@@ -2457,9 +2491,10 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (Tok.is(tok::kw_template)) {
assert(!TemplateInfo.TemplateParams &&
"Nested template improperly parsed?");
+ ObjCDeclContextSwitch ObjCDC(*this);
SourceLocation DeclEnd;
return DeclGroupPtrTy::make(
- DeclGroupRef(ParseDeclarationStartingWithTemplate(
+ DeclGroupRef(ParseTemplateDeclarationOrSpecialization(
Declarator::MemberContext, DeclEnd, AS, AccessAttrs)));
}
@@ -2864,9 +2899,8 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
assert(Tok.isOneOf(tok::equal, tok::l_brace)
&& "Data member initializer not starting with '=' or '{'");
- EnterExpressionEvaluationContext Context(Actions,
- Sema::PotentiallyEvaluated,
- D);
+ EnterExpressionEvaluationContext Context(
+ Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, D);
if (TryConsumeToken(tok::equal, EqualLoc)) {
if (Tok.is(tok::kw_delete)) {
// In principle, an initializer of '= delete p;' is legal, but it will
@@ -2957,56 +2991,50 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc,
Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs,
DeclSpec::TST TagType, Decl *TagDecl) {
- if (getLangOpts().MicrosoftExt &&
- Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) {
+ switch (Tok.getKind()) {
+ case tok::kw___if_exists:
+ case tok::kw___if_not_exists:
ParseMicrosoftIfExistsClassDeclaration(TagType, AS);
return nullptr;
- }
- // Check for extraneous top-level semicolon.
- if (Tok.is(tok::semi)) {
+ case tok::semi:
+ // Check for extraneous top-level semicolon.
ConsumeExtraSemi(InsideStruct, TagType);
return nullptr;
- }
- if (Tok.is(tok::annot_pragma_vis)) {
+ // Handle pragmas that can appear as member declarations.
+ case tok::annot_pragma_vis:
HandlePragmaVisibility();
return nullptr;
- }
-
- if (Tok.is(tok::annot_pragma_pack)) {
+ case tok::annot_pragma_pack:
HandlePragmaPack();
return nullptr;
- }
-
- if (Tok.is(tok::annot_pragma_align)) {
+ case tok::annot_pragma_align:
HandlePragmaAlign();
return nullptr;
- }
-
- if (Tok.is(tok::annot_pragma_ms_pointers_to_members)) {
+ case tok::annot_pragma_ms_pointers_to_members:
HandlePragmaMSPointersToMembers();
return nullptr;
- }
-
- if (Tok.is(tok::annot_pragma_ms_pragma)) {
+ case tok::annot_pragma_ms_pragma:
HandlePragmaMSPragma();
return nullptr;
- }
-
- if (Tok.is(tok::annot_pragma_ms_vtordisp)) {
+ case tok::annot_pragma_ms_vtordisp:
HandlePragmaMSVtorDisp();
return nullptr;
- }
+ case tok::annot_pragma_dump:
+ HandlePragmaDump();
+ return nullptr;
- // If we see a namespace here, a close brace was missing somewhere.
- if (Tok.is(tok::kw_namespace)) {
+ case tok::kw_namespace:
+ // If we see a namespace here, a close brace was missing somewhere.
DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl));
return nullptr;
- }
- AccessSpecifier NewAS = getAccessSpecifierIfPresent();
- if (NewAS != AS_none) {
+ case tok::kw_public:
+ case tok::kw_protected:
+ case tok::kw_private: {
+ AccessSpecifier NewAS = getAccessSpecifierIfPresent();
+ assert(NewAS != AS_none);
// Current token is a C++ access specifier.
AS = NewAS;
SourceLocation ASLoc = Tok.getLocation();
@@ -3041,12 +3069,13 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
return nullptr;
}
- if (Tok.is(tok::annot_pragma_openmp))
+ case tok::annot_pragma_openmp:
return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, AccessAttrs, TagType,
TagDecl);
- // Parse all the comma separated declarators.
- return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList());
+ default:
+ return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList());
+ }
}
/// ParseCXXMemberSpecification - Parse the class definition.
@@ -3381,7 +3410,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
if (TemplateId->Kind == TNK_Type_template ||
TemplateId->Kind == TNK_Dependent_template_name) {
- AnnotateTemplateIdTokenAsType();
+ AnnotateTemplateIdTokenAsType(/*IsClassName*/true);
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
TemplateTypeTy = getTypeAnnotation(Tok);
}
@@ -3817,36 +3846,44 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
return false;
}
- if (ScopeName && ScopeName->getName() == "gnu")
+ 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, nullptr);
- else {
- unsigned NumArgs =
+ return true;
+ }
+
+ unsigned NumArgs;
+ // Some Clang-scoped attributes have some special parsing behavior.
+ if (ScopeName && ScopeName->getName() == "clang")
+ NumArgs =
+ ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
+ ScopeLoc, AttributeList::AS_CXX11);
+ else
+ NumArgs =
ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, AttributeList::AS_CXX11);
-
- const AttributeList *Attr = Attrs.getList();
- if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {
- // If the attribute is a standard or built-in attribute and we are
- // parsing an argument list, we need to determine whether this attribute
- // was allowed to have an argument list (such as [[deprecated]]), and how
- // many arguments were parsed (so we can diagnose on [[deprecated()]]).
- if (Attr->getMaxArgs() && !NumArgs) {
- // The attribute was allowed to have arguments, but none were provided
- // even though the attribute parsed successfully. This is an error.
- Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName;
- Attr->setInvalid(true);
- } else if (!Attr->getMaxArgs()) {
- // The attribute parsed successfully, but was not allowed to have any
- // arguments. It doesn't matter whether any were provided -- the
- // presence of the argument list (even if empty) is diagnosed.
- Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)
- << AttrName
- << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc));
- Attr->setInvalid(true);
- }
+
+ const AttributeList *Attr = Attrs.getList();
+ if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {
+ // If the attribute is a standard or built-in attribute and we are
+ // parsing an argument list, we need to determine whether this attribute
+ // was allowed to have an argument list (such as [[deprecated]]), and how
+ // many arguments were parsed (so we can diagnose on [[deprecated()]]).
+ if (Attr->getMaxArgs() && !NumArgs) {
+ // The attribute was allowed to have arguments, but none were provided
+ // even though the attribute parsed successfully. This is an error.
+ Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName;
+ Attr->setInvalid(true);
+ } else if (!Attr->getMaxArgs()) {
+ // The attribute parsed successfully, but was not allowed to have any
+ // arguments. It doesn't matter whether any were provided -- the
+ // presence of the argument list (even if empty) is diagnosed.
+ Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)
+ << AttrName
+ << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc));
+ Attr->setInvalid(true);
}
}
return true;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 852e2269393a..ad45ab114fde 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -21,10 +21,10 @@
///
//===----------------------------------------------------------------------===//
-#include "RAIIObjectsForParser.h"
+#include "clang/Parse/Parser.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/PrettyStackTrace.h"
-#include "clang/Parse/Parser.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
@@ -198,8 +198,8 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) {
// An expression is potentially evaluated unless it appears where an
// integral constant expression is required (see 5.19) [...].
// C++98 and C++11 have no such rule, but this is only a defect in C++98.
- EnterExpressionEvaluationContext ConstantEvaluated(Actions,
- Sema::ConstantEvaluated);
+ EnterExpressionEvaluationContext ConstantEvaluated(
+ Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
ExprResult LHS(ParseCastExpression(false, false, isTypeCast));
ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
@@ -473,12 +473,14 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
///
ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand,
- TypeCastState isTypeCast) {
+ TypeCastState isTypeCast,
+ bool isVectorLiteral) {
bool NotCastExpr;
ExprResult Res = ParseCastExpression(isUnaryExpression,
isAddressOfOperand,
NotCastExpr,
- isTypeCast);
+ isTypeCast,
+ isVectorLiteral);
if (NotCastExpr)
Diag(Tok, diag::err_expected_expression);
return Res;
@@ -674,6 +676,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
/// '__is_union'
///
/// [Clang] unary-type-trait:
+/// '__is_aggregate'
/// '__trivially_copyable'
///
/// binary-type-trait:
@@ -694,7 +697,8 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand,
bool &NotCastExpr,
- TypeCastState isTypeCast) {
+ TypeCastState isTypeCast,
+ bool isVectorLiteral) {
ExprResult Res;
tok::TokenKind SavedKind = Tok.getKind();
NotCastExpr = false;
@@ -722,6 +726,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
isTypeCast == IsTypeCast, CastTy, RParenLoc);
+ if (isVectorLiteral)
+ return Res;
+
switch (ParenExprType) {
case SimpleExpr: break; // Nothing else to do.
case CompoundStmt: break; // Nothing else to do.
@@ -798,6 +805,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
= RTT_JOIN(tok::kw_,Name)
REVERTIBLE_TYPE_TRAIT(__is_abstract);
+ REVERTIBLE_TYPE_TRAIT(__is_aggregate);
REVERTIBLE_TYPE_TRAIT(__is_arithmetic);
REVERTIBLE_TYPE_TRAIT(__is_array);
REVERTIBLE_TYPE_TRAIT(__is_assignable);
@@ -1307,7 +1315,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// C++11 [expr.unary.noexcept]p1:
// The noexcept operator determines whether the evaluation of its operand,
// which is an unevaluated operand, can throw an exception.
- EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated);
ExprResult Result = ParseExpression();
T.consumeClose();
@@ -1693,6 +1702,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
/*AllowDestructorName=*/true,
/*AllowConstructorName=*/
getLangOpts().MicrosoftExt,
+ /*AllowDeductionGuide=*/false,
ObjectType, TemplateKWLoc, Name)) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
LHS = ExprError();
@@ -1875,9 +1885,10 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
if (!Name)
return ExprError();
-
- EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
- Sema::ReuseLambdaContextDecl);
+
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated,
+ Sema::ReuseLambdaContextDecl);
return Actions.ActOnSizeofParameterPackExpr(getCurScope(),
OpTok.getLocation(),
@@ -1888,8 +1899,9 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))
Diag(OpTok, diag::warn_cxx98_compat_alignof);
- EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
- Sema::ReuseLambdaContextDecl);
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated,
+ Sema::ReuseLambdaContextDecl);
bool isCastExpr;
ParsedType CastTy;
@@ -2349,6 +2361,48 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc);
}
+ if (Tok.is(tok::l_paren)) {
+ // This could be OpenCL vector Literals
+ if (getLangOpts().OpenCL)
+ {
+ TypeResult Ty;
+ {
+ InMessageExpressionRAIIObject InMessage(*this, false);
+ Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
+ }
+ if(Ty.isInvalid())
+ {
+ return ExprError();
+ }
+ QualType QT = Ty.get().get().getCanonicalType();
+ if (QT->isVectorType())
+ {
+ // We parsed '(' vector-type-name ')' followed by '('
+
+ // Parse the cast-expression that follows it next.
+ // isVectorLiteral = true will make sure we don't parse any
+ // Postfix expression yet
+ Result = ParseCastExpression(/*isUnaryExpression=*/false,
+ /*isAddressOfOperand=*/false,
+ /*isTypeCast=*/IsTypeCast,
+ /*isVectorLiteral=*/true);
+
+ if (!Result.isInvalid()) {
+ Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc,
+ DeclaratorInfo, CastTy,
+ RParenLoc, Result.get());
+ }
+
+ // After we performed the cast we can check for postfix-expr pieces.
+ if (!Result.isInvalid()) {
+ Result = ParsePostfixExpressionSuffix(Result);
+ }
+
+ return Result;
+ }
+ }
+ }
+
if (ExprType == CastExpr) {
// We parsed '(' type-name ')' and the thing after it wasn't a '{'.
@@ -2520,7 +2574,8 @@ ExprResult Parser::ParseGenericSelectionExpression() {
{
// C11 6.5.1.1p3 "The controlling expression of a generic selection is
// not evaluated."
- EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated);
ControllingExpr =
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
if (ControllingExpr.isInvalid()) {
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 124266a42bd5..671a815911f3 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -10,13 +10,13 @@
// This file implements the Expression parsing implementation for C++.
//
//===----------------------------------------------------------------------===//
+#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/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
@@ -141,13 +141,16 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType,
/// filled in with the leading identifier in the last component of the
/// nested-name-specifier, if any.
///
+/// \param OnlyNamespace If true, only considers namespaces in lookup.
+///
/// \returns true if there was an error parsing a scope specifier
bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
ParsedType ObjectType,
bool EnteringContext,
bool *MayBePseudoDestructor,
bool IsTypename,
- IdentifierInfo **LastII) {
+ IdentifierInfo **LastII,
+ bool OnlyNamespace) {
assert(getLangOpts().CPlusPlus &&
"Call sites of this function should be guarded by checking for C++");
@@ -216,7 +219,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
SourceLocation EndLoc = ParseDecltypeSpecifier(DS);
SourceLocation CCLoc;
- if (!TryConsumeToken(tok::coloncolon, CCLoc)) {
+ // Work around a standard defect: 'decltype(auto)::' is not a
+ // nested-name-specifier.
+ if (DS.getTypeSpecType() == DeclSpec::TST_decltype_auto ||
+ !TryConsumeToken(tok::coloncolon, CCLoc)) {
AnnotateExistingDecltypeSpecifier(DS, DeclLoc, EndLoc);
return false;
}
@@ -310,11 +316,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// Commit to parsing the template-id.
TPA.Commit();
TemplateTy Template;
- if (TemplateNameKind TNK
- = Actions.ActOnDependentTemplateName(getCurScope(),
- SS, TemplateKWLoc, TemplateName,
- ObjectType, EnteringContext,
- Template)) {
+ if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName(
+ getCurScope(), SS, TemplateKWLoc, TemplateName, ObjectType,
+ EnteringContext, Template, /*AllowInjectedClassName*/ true)) {
if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateKWLoc,
TemplateName, false))
return true;
@@ -449,9 +453,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
bool IsCorrectedToColon = false;
bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : nullptr;
- if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), IdInfo,
- EnteringContext, SS,
- false, CorrectionFlagPtr)) {
+ if (Actions.ActOnCXXNestedNameSpecifier(
+ getCurScope(), IdInfo, EnteringContext, SS, false,
+ CorrectionFlagPtr, OnlyNamespace)) {
// Identifier is not recognized as a nested name, but we can have
// mistyped '::' instead of ':'.
if (CorrectionFlagPtr && IsCorrectedToColon) {
@@ -509,12 +513,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
Diag(Tok.getLocation(), DiagID)
<< II.getName()
<< FixItHint::CreateInsertion(Tok.getLocation(), "template ");
-
- if (TemplateNameKind TNK
- = Actions.ActOnDependentTemplateName(getCurScope(),
- SS, SourceLocation(),
- TemplateName, ObjectType,
- EnteringContext, Template)) {
+
+ if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName(
+ getCurScope(), SS, SourceLocation(), TemplateName, ObjectType,
+ EnteringContext, Template, /*AllowInjectedClassName*/ true)) {
// Consume the identifier.
ConsumeToken();
if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),
@@ -550,6 +552,7 @@ ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOpe
/*EnteringContext=*/false,
/*AllowDestructorName=*/false,
/*AllowConstructorName=*/false,
+ /*AllowDeductionGuide=*/false,
/*ObjectType=*/nullptr, TemplateKWLoc, Name))
return ExprError();
@@ -863,8 +866,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// Each lambda init-capture forms its own full expression, which clears
// Actions.MaybeODRUseExprs. So create an expression evaluation context
// to save the necessary state, and restore it later.
- EnterExpressionEvaluationContext EC(Actions,
- Sema::PotentiallyEvaluated);
+ EnterExpressionEvaluationContext EC(
+ Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
if (TryConsumeToken(tok::equal))
InitKind = LambdaCaptureInitKind::CopyInit;
@@ -1402,8 +1405,9 @@ ExprResult Parser::ParseCXXTypeid() {
// We enter the unevaluated context before trying to determine whether we
// have a type-id, because the tentative parse logic will try to resolve
// names, and must treat them as unevaluated.
- EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
- Sema::ReuseLambdaContextDecl);
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated,
+ Sema::ReuseLambdaContextDecl);
if (isTypeIdInParens()) {
TypeResult Ty = ParseTypeName();
@@ -1466,7 +1470,8 @@ ExprResult Parser::ParseCXXUuidof() {
Ty.get().getAsOpaquePtr(),
T.getCloseLocation());
} else {
- EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated);
Result = ParseExpression();
// Match the ')'.
@@ -1643,9 +1648,10 @@ ExprResult Parser::ParseCXXThis() {
/// typename-specifier '(' expression-list[opt] ')'
/// [C++0x] typename-specifier braced-init-list
///
+/// In C++1z onwards, the type specifier can also be a template-name.
ExprResult
Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, Declarator::FunctionalCastContext);
ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
assert((Tok.is(tok::l_paren) ||
@@ -2020,9 +2026,11 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
case UnqualifiedId::IK_OperatorFunctionId:
case UnqualifiedId::IK_LiteralOperatorId:
if (AssumeTemplateId) {
- TNK = Actions.ActOnDependentTemplateName(getCurScope(), SS, TemplateKWLoc,
- Id, ObjectType, EnteringContext,
- Template);
+ // We defer the injected-class-name checks until we've found whether
+ // this template-id is used to form a nested-name-specifier or not.
+ TNK = Actions.ActOnDependentTemplateName(
+ getCurScope(), SS, TemplateKWLoc, Id, ObjectType, EnteringContext,
+ Template, /*AllowInjectedClassName*/ true);
if (TNK == TNK_Non_template)
return true;
} else {
@@ -2051,10 +2059,9 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
Diag(Id.StartLocation, diag::err_missing_dependent_template_keyword)
<< Name
<< FixItHint::CreateInsertion(Id.StartLocation, "template ");
- TNK = Actions.ActOnDependentTemplateName(getCurScope(),
- SS, TemplateKWLoc, Id,
- ObjectType, EnteringContext,
- Template);
+ TNK = Actions.ActOnDependentTemplateName(
+ getCurScope(), SS, TemplateKWLoc, Id, ObjectType, EnteringContext,
+ Template, /*AllowInjectedClassName*/ true);
if (TNK == TNK_Non_template)
return true;
}
@@ -2077,10 +2084,9 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
bool MemberOfUnknownSpecialization;
TemplateName.setIdentifier(Name, NameLoc);
if (ObjectType) {
- TNK = Actions.ActOnDependentTemplateName(getCurScope(),
- SS, TemplateKWLoc, TemplateName,
- ObjectType, EnteringContext,
- Template);
+ TNK = Actions.ActOnDependentTemplateName(
+ getCurScope(), SS, TemplateKWLoc, TemplateName, ObjectType,
+ EnteringContext, Template, /*AllowInjectedClassName*/ true);
if (TNK == TNK_Non_template)
return true;
} else {
@@ -2155,7 +2161,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
// Constructor and destructor names.
TypeResult Type
= Actions.ActOnTemplateIdType(SS, TemplateKWLoc,
- Template, NameLoc,
+ Template, Name, NameLoc,
LAngleLoc, TemplateArgsPtr, RAngleLoc,
/*IsCtorOrDtorName=*/true);
if (Type.isInvalid())
@@ -2432,6 +2438,8 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
///
/// \param AllowConstructorName whether we allow parsing a constructor name.
///
+/// \param AllowDeductionGuide whether we allow parsing a deduction guide name.
+///
/// \param ObjectType if this unqualified-id occurs within a member access
/// expression, the type of the base object whose member is being accessed.
///
@@ -2441,6 +2449,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
bool AllowDestructorName,
bool AllowConstructorName,
+ bool AllowDeductionGuide,
ParsedType ObjectType,
SourceLocation& TemplateKWLoc,
UnqualifiedId &Result) {
@@ -2469,6 +2478,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
return false;
}
+ ParsedTemplateTy TemplateName;
if (AllowConstructorName &&
Actions.isCurrentClassName(*Id, getCurScope(), &SS)) {
// We have parsed a constructor name.
@@ -2477,6 +2487,12 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
/*IsCtorOrDtorName=*/true,
/*NonTrivialTypeSourceInfo=*/true);
Result.setConstructorName(Ty, IdLoc, IdLoc);
+ } else if (getLangOpts().CPlusPlus1z &&
+ AllowDeductionGuide && SS.isEmpty() &&
+ Actions.isDeductionGuideName(getCurScope(), *Id, IdLoc,
+ &TemplateName)) {
+ // We have parsed a template-name naming a deduction guide.
+ Result.setDeductionGuideName(TemplateName, IdLoc);
} else {
// We have parsed an identifier.
Result.setIdentifier(Id, IdLoc);
@@ -2569,7 +2585,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
if (SS.isEmpty() && Tok.is(tok::kw_decltype)) {
DeclSpec DS(AttrFactory);
SourceLocation EndLoc = ParseDecltypeSpecifier(DS);
- if (ParsedType Type = Actions.getDestructorType(DS, ObjectType)) {
+ if (ParsedType Type =
+ Actions.getDestructorTypeForDecltype(DS, ObjectType)) {
Result.setDestructorName(TildeLoc, Type, EndLoc);
return false;
}
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index fa6b75daed92..f48d01e0f630 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -11,9 +11,9 @@
//
//===----------------------------------------------------------------------===//
-#include "RAIIObjectsForParser.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/SmallString.h"
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 81761bf8d2d8..77e63efc065e 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -12,10 +12,10 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/Parser.h"
-#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
@@ -137,8 +137,7 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
while (1) {
MaybeSkipAttributes(tok::objc_class);
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected) << tok::identifier;
+ if (expectIdentifier()) {
SkipUntil(tok::semi);
return Actions.ConvertDeclToDeclGroup(nullptr);
}
@@ -229,11 +228,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
MaybeSkipAttributes(tok::objc_interface);
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected)
- << tok::identifier; // missing class or category name.
- return nullptr;
- }
+ if (expectIdentifier())
+ return nullptr; // missing class or category name.
// We have a class or category name - consume it.
IdentifierInfo *nameId = Tok.getIdentifierInfo();
@@ -278,11 +274,6 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return nullptr;
-
- if (!attrs.empty()) { // categories don't support attributes.
- Diag(nameLoc, diag::err_objc_no_attributes_on_category);
- attrs.clear();
- }
// Next, we need to check for any protocol references.
assert(LAngleLoc.isInvalid() && "Cannot have already parsed protocols");
@@ -294,16 +285,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
/*consumeLastToken=*/true))
return nullptr;
- Decl *CategoryType =
- Actions.ActOnStartCategoryInterface(AtLoc,
- nameId, nameLoc,
- typeParameterList,
- categoryId, categoryLoc,
- ProtocolRefs.data(),
- ProtocolRefs.size(),
- ProtocolLocs.data(),
- EndProtoLoc);
-
+ Decl *CategoryType = Actions.ActOnStartCategoryInterface(
+ AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc,
+ ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(),
+ EndProtoLoc, attrs.getList());
+
if (Tok.is(tok::l_brace))
ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc);
@@ -329,11 +315,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
return nullptr;
}
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected)
- << tok::identifier; // missing super class name.
- return nullptr;
- }
+ if (expectIdentifier())
+ return nullptr; // missing super class name.
superClassId = Tok.getIdentifierInfo();
superClassLoc = ConsumeToken();
@@ -929,7 +912,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
if (IsSetter) {
DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
- DS.setSetterName(SelIdent);
+ DS.setSetterName(SelIdent, SelLoc);
if (ExpectAndConsume(tok::colon,
diag::err_expected_colon_after_setter_name)) {
@@ -938,7 +921,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
}
} else {
DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
- DS.setGetterName(SelIdent);
+ DS.setGetterName(SelIdent, SelLoc);
}
} else if (II->isStr("nonnull")) {
if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
@@ -1448,12 +1431,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
cutOffParsing();
return nullptr;
}
-
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected)
- << tok::identifier; // missing argument name.
- break;
- }
+
+ if (expectIdentifier())
+ break; // missing argument name.
ArgInfo.Name = Tok.getIdentifierInfo();
ArgInfo.NameLoc = Tok.getLocation();
@@ -1562,8 +1542,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
return true;
}
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected) << tok::identifier;
+ if (expectIdentifier()) {
SkipUntil(tok::greater, StopAtSemi);
return true;
}
@@ -2045,10 +2024,8 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
MaybeSkipAttributes(tok::objc_protocol);
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected) << tok::identifier; // missing protocol name.
- return nullptr;
- }
+ if (expectIdentifier())
+ return nullptr; // missing protocol name.
// Save the protocol name, then consume it.
IdentifierInfo *protocolName = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken();
@@ -2068,8 +2045,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
// Parse the list of forward declarations.
while (1) {
ConsumeToken(); // the ','
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected) << tok::identifier;
+ if (expectIdentifier()) {
SkipUntil(tok::semi);
return nullptr;
}
@@ -2136,11 +2112,8 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
MaybeSkipAttributes(tok::objc_implementation);
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected)
- << tok::identifier; // missing class or category name.
- return nullptr;
- }
+ if (expectIdentifier())
+ return nullptr; // missing class or category name.
// We have a class or category name - consume it.
IdentifierInfo *nameId = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken(); // consume class or category name
@@ -2210,11 +2183,8 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
IdentifierInfo *superClassId = nullptr;
if (TryConsumeToken(tok::colon)) {
// We have a super class
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected)
- << tok::identifier; // missing super class name.
- return nullptr;
- }
+ if (expectIdentifier())
+ return nullptr; // missing super class name.
superClassId = Tok.getIdentifierInfo();
superClassLoc = ConsumeToken(); // Consume super class name
}
@@ -2314,16 +2284,12 @@ Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
"ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
ConsumeToken(); // consume compatibility_alias
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected) << tok::identifier;
+ if (expectIdentifier())
return nullptr;
- }
IdentifierInfo *aliasId = Tok.getIdentifierInfo();
SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected) << tok::identifier;
+ if (expectIdentifier())
return nullptr;
- }
IdentifierInfo *classId = Tok.getIdentifierInfo();
SourceLocation classLoc = ConsumeToken(); // consume class-name;
ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias");
@@ -2371,11 +2337,9 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
cutOffParsing();
return nullptr;
}
-
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected) << tok::identifier;
+
+ if (expectIdentifier())
break;
- }
propertyIvar = Tok.getIdentifierInfo();
propertyIvarLoc = ConsumeToken(); // consume ivar-name
}
@@ -2433,9 +2397,8 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
cutOffParsing();
return nullptr;
}
-
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected) << tok::identifier;
+
+ if (expectIdentifier()) {
SkipUntil(tok::semi);
return nullptr;
}
@@ -3571,8 +3534,8 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
- if (Tok.isNot(tok::identifier))
- return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
+ if (expectIdentifier())
+ return ExprError();
IdentifierInfo *protocolId = Tok.getIdentifierInfo();
SourceLocation ProtoIdLoc = ConsumeToken();
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index cab7d3432db3..dfb0438ba8ce 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -11,11 +11,11 @@
///
//===----------------------------------------------------------------------===//
-#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -806,7 +806,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
/// annot_pragma_openmp_end
///
StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
- AllowedContsructsKind Allowed) {
+ AllowedConstructsKind Allowed) {
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
ParenBraceBracketBalancer BalancerRAIIObj(*this);
SmallVector<OMPClause *, 5> Clauses;
@@ -1053,7 +1053,7 @@ bool Parser::ParseOpenMPSimpleVarList(
IsCorrect = false;
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
- } else if (ParseUnqualifiedId(SS, false, false, false, nullptr,
+ } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
TemplateKWLoc, Name)) {
IsCorrect = false;
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
@@ -1557,8 +1557,9 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
}
return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
/*AllowDestructorName*/ false,
- /*AllowConstructorName*/ false, nullptr,
- TemplateKWLoc, ReductionId);
+ /*AllowConstructorName*/ false,
+ /*AllowDeductionGuide*/ false,
+ nullptr, TemplateKWLoc, ReductionId);
}
/// Parses clauses with list.
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 89733237c153..c8de6b35f9ef 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -11,13 +11,13 @@
//
//===----------------------------------------------------------------------===//
-#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/PragmaKinds.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/LoopHint.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/StringSwitch.h"
@@ -86,6 +86,12 @@ struct PragmaFPContractHandler : public PragmaHandler {
Token &FirstToken) override;
};
+struct PragmaFPHandler : public PragmaHandler {
+ PragmaFPHandler() : PragmaHandler("fp") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
struct PragmaNoOpenMPHandler : public PragmaHandler {
PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
@@ -266,6 +272,9 @@ void Parser::initializePragmaHandlers() {
NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
PP.AddPragmaHandler(NoUnrollHintHandler.get());
+
+ FPHandler.reset(new PragmaFPHandler());
+ PP.AddPragmaHandler("clang", FPHandler.get());
}
void Parser::resetPragmaHandlers() {
@@ -344,6 +353,9 @@ void Parser::resetPragmaHandlers() {
PP.RemovePragmaHandler(NoUnrollHintHandler.get());
NoUnrollHintHandler.reset();
+
+ PP.RemovePragmaHandler("clang", FPHandler.get());
+ FPHandler.reset();
}
/// \brief Handle the annotation token produced for #pragma unused(...)
@@ -454,7 +466,21 @@ void Parser::HandlePragmaFPContract() {
tok::OnOffSwitch OOS =
static_cast<tok::OnOffSwitch>(
reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
- Actions.ActOnPragmaFPContract(OOS);
+
+ LangOptions::FPContractModeKind FPC;
+ switch (OOS) {
+ case tok::OOS_ON:
+ FPC = LangOptions::FPC_On;
+ break;
+ case tok::OOS_OFF:
+ FPC = LangOptions::FPC_Off;
+ break;
+ case tok::OOS_DEFAULT:
+ FPC = getLangOpts().getDefaultFPContractMode();
+ break;
+ }
+
+ Actions.ActOnPragmaFPContract(FPC);
ConsumeToken(); // The annotation token.
}
@@ -1947,6 +1973,129 @@ void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
}
+namespace {
+/// Used as the annotation value for tok::annot_pragma_fp.
+struct TokFPAnnotValue {
+ enum FlagKinds { Contract };
+ enum FlagValues { On, Off, Fast };
+
+ FlagKinds FlagKind;
+ FlagValues FlagValue;
+};
+} // end anonymous namespace
+
+void PragmaFPHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ // fp
+ Token PragmaName = Tok;
+ SmallVector<Token, 1> TokenList;
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
+ << /*MissingOption=*/true << "";
+ return;
+ }
+
+ while (Tok.is(tok::identifier)) {
+ IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
+
+ auto FlagKind =
+ llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
+ OptionInfo->getName())
+ .Case("contract", TokFPAnnotValue::Contract)
+ .Default(None);
+ if (!FlagKind) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
+ << /*MissingOption=*/false << OptionInfo;
+ return;
+ }
+ PP.Lex(Tok);
+
+ // Read '('
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
+ << PP.getSpelling(Tok) << OptionInfo->getName();
+ return;
+ }
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+
+ auto FlagValue =
+ llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>(
+ II->getName())
+ .Case("on", TokFPAnnotValue::On)
+ .Case("off", TokFPAnnotValue::Off)
+ .Case("fast", TokFPAnnotValue::Fast)
+ .Default(llvm::None);
+
+ if (!FlagValue) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
+ << PP.getSpelling(Tok) << OptionInfo->getName();
+ return;
+ }
+ PP.Lex(Tok);
+
+ // Read ')'
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
+ return;
+ }
+ PP.Lex(Tok);
+
+ auto *AnnotValue = new (PP.getPreprocessorAllocator())
+ TokFPAnnotValue{*FlagKind, *FlagValue};
+ // Generate the loop hint token.
+ Token FPTok;
+ FPTok.startToken();
+ FPTok.setKind(tok::annot_pragma_fp);
+ FPTok.setLocation(PragmaName.getLocation());
+ FPTok.setAnnotationEndLoc(PragmaName.getLocation());
+ FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
+ TokenList.push_back(FPTok);
+ }
+
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "clang fp";
+ return;
+ }
+
+ auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
+ std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
+
+ PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
+ /*DisableMacroExpansion=*/false);
+}
+
+void Parser::HandlePragmaFP() {
+ assert(Tok.is(tok::annot_pragma_fp));
+ auto *AnnotValue =
+ reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
+
+ LangOptions::FPContractModeKind FPC;
+ switch (AnnotValue->FlagValue) {
+ case TokFPAnnotValue::On:
+ FPC = LangOptions::FPC_On;
+ break;
+ case TokFPAnnotValue::Fast:
+ FPC = LangOptions::FPC_Fast;
+ break;
+ case TokFPAnnotValue::Off:
+ FPC = LangOptions::FPC_Off;
+ break;
+ }
+
+ Actions.ActOnPragmaFPContract(FPC);
+ ConsumeToken(); // The annotation token.
+}
+
/// \brief Parses loop or unroll pragma hint value and fills in Info.
static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
Token Option, bool ValueInParens,
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 30e392fa3c94..eaff9fe8eedf 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -12,10 +12,10 @@
//
//===----------------------------------------------------------------------===//
-#include "RAIIObjectsForParser.h"
#include "clang/Basic/Attributes.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Parse/Parser.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/LoopHint.h"
#include "clang/Sema/PrettyDeclStackTrace.h"
@@ -97,7 +97,7 @@ StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc,
///
StmtResult
Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
- AllowedContsructsKind Allowed,
+ AllowedConstructsKind Allowed,
SourceLocation *TrailingElseLoc) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
@@ -150,7 +150,7 @@ private:
StmtResult
Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts,
- AllowedContsructsKind Allowed, SourceLocation *TrailingElseLoc,
+ AllowedConstructsKind Allowed, SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs) {
const char *SemiError = nullptr;
StmtResult Res;
@@ -341,6 +341,12 @@ Retry:
ConsumeToken();
return StmtError();
+ case tok::annot_pragma_fp:
+ ProhibitAttributes(Attrs);
+ Diag(Tok, diag::err_pragma_fp_scope);
+ ConsumeToken();
+ return StmtError();
+
case tok::annot_pragma_opencl_extension:
ProhibitAttributes(Attrs);
HandlePragmaOpenCLExtension();
@@ -900,6 +906,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() {
case tok::annot_pragma_fp_contract:
HandlePragmaFPContract();
break;
+ case tok::annot_pragma_fp:
+ HandlePragmaFP();
+ break;
case tok::annot_pragma_ms_pointers_to_members:
HandlePragmaMSPointersToMembers();
break;
@@ -1179,7 +1188,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
StmtResult ThenStmt;
{
EnterExpressionEvaluationContext PotentiallyDiscarded(
- Actions, Sema::DiscardedStatement, nullptr, false,
+ Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr,
+ false,
/*ShouldEnter=*/ConstexprCondition && !*ConstexprCondition);
ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc);
}
@@ -1212,7 +1222,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
Tok.is(tok::l_brace));
EnterExpressionEvaluationContext PotentiallyDiscarded(
- Actions, Sema::DiscardedStatement, nullptr, false,
+ Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr,
+ false,
/*ShouldEnter=*/ConstexprCondition && *ConstexprCondition);
ElseStmt = ParseStatement();
@@ -1898,12 +1909,12 @@ StmtResult Parser::ParseReturnStatement() {
}
}
if (IsCoreturn)
- return Actions.ActOnCoreturnStmt(ReturnLoc, R.get());
+ return Actions.ActOnCoreturnStmt(getCurScope(), ReturnLoc, R.get());
return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope());
}
StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts,
- AllowedContsructsKind Allowed,
+ AllowedConstructsKind Allowed,
SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs) {
// Create temporary attribute list.
diff --git a/lib/Parse/ParseStmtAsm.cpp b/lib/Parse/ParseStmtAsm.cpp
index 293de78505ef..d6f16bb0cb79 100644
--- a/lib/Parse/ParseStmtAsm.cpp
+++ b/lib/Parse/ParseStmtAsm.cpp
@@ -12,10 +12,10 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/Parser.h"
-#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -224,6 +224,7 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
/*EnteringContext=*/false,
/*AllowDestructorName=*/false,
/*AllowConstructorName=*/false,
+ /*AllowDeductionGuide=*/false,
/*ObjectType=*/nullptr, TemplateKWLoc, Id);
// Perform the lookup.
Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info,
@@ -451,12 +452,17 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
// We're no longer in a comment.
InAsmComment = false;
if (isAsm) {
- // If this is a new __asm {} block we want to process it seperately
+ // If this is a new __asm {} block we want to process it separately
// from the single-line __asm statements
if (PP.LookAhead(0).is(tok::l_brace))
break;
LineNo = SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second);
SkippedStartOfLine = Tok.isAtStartOfLine();
+ } else if (Tok.is(tok::semi)) {
+ // A multi-line asm-statement, where next line is a comment
+ InAsmComment = true;
+ FID = ExpLoc.first;
+ LineNo = SrcMgr.getLineNumber(FID, ExpLoc.second);
}
} else if (!InAsmComment && Tok.is(tok::r_brace)) {
// In MSVC mode, braces only participate in brace matching and
@@ -615,10 +621,11 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
MII.get(), IP.get(), 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());
+ // Filter out "fpsw" and "mxcsr". They aren't valid GCC asm clobber
+ // constraints. Clang always adds fpsr to the clobber list anyway.
+ llvm::erase_if(Clobbers, [](const std::string &C) {
+ return C == "fpsw" || C == "mxcsr";
+ });
// Build the vector of clobber StringRefs.
ClobberRefs.insert(ClobberRefs.end(), Clobbers.begin(), Clobbers.end());
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 6a09ea7abca0..d2b18e7c0a81 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -11,11 +11,11 @@
//
//===----------------------------------------------------------------------===//
-#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
@@ -701,8 +701,8 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
// end of the template-parameter-list rather than a greater-than
// operator.
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
- EnterExpressionEvaluationContext ConstantEvaluated(Actions,
- Sema::ConstantEvaluated);
+ EnterExpressionEvaluationContext ConstantEvaluated(
+ Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
DefaultArg = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
if (DefaultArg.isInvalid())
@@ -1000,13 +1000,13 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
// Build the annotation token.
if (TNK == TNK_Type_template && AllowTypeAnnotation) {
- TypeResult Type
- = Actions.ActOnTemplateIdType(SS, TemplateKWLoc,
- Template, TemplateNameLoc,
- LAngleLoc, TemplateArgsPtr, RAngleLoc);
+ TypeResult Type = Actions.ActOnTemplateIdType(
+ SS, TemplateKWLoc, Template, TemplateName.Identifier,
+ TemplateNameLoc, LAngleLoc, TemplateArgsPtr, RAngleLoc);
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 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.
TryConsumeToken(tok::greater);
return true;
}
@@ -1064,7 +1064,12 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
/// If there was a failure when forming the type from the template-id,
/// a type annotation token will still be created, but will have a
/// NULL type pointer to signify an error.
-void Parser::AnnotateTemplateIdTokenAsType() {
+///
+/// \param IsClassName Is this template-id appearing in a context where we
+/// know it names a class, such as in an elaborated-type-specifier or
+/// base-specifier? ('typename' and 'template' are unneeded and disallowed
+/// in those contexts.)
+void Parser::AnnotateTemplateIdTokenAsType(bool IsClassName) {
assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens");
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
@@ -1079,10 +1084,13 @@ void Parser::AnnotateTemplateIdTokenAsType() {
= Actions.ActOnTemplateIdType(TemplateId->SS,
TemplateId->TemplateKWLoc,
TemplateId->Template,
+ TemplateId->Name,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
- TemplateId->RAngleLoc);
+ TemplateId->RAngleLoc,
+ /*IsCtorOrDtorName*/false,
+ IsClassName);
// Create the new "type" annotation token.
Tok.setKind(tok::annot_typename);
setTypeAnnotation(Tok, Type.isInvalid() ? nullptr : Type.get());
@@ -1267,7 +1275,8 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) {
bool
Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
// Template argument lists are constant-evaluation contexts.
- EnterExpressionEvaluationContext EvalContext(Actions,Sema::ConstantEvaluated);
+ EnterExpressionEvaluationContext EvalContext(
+ Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
ColonProtectionRAIIObject ColonProtection(*this, false);
do {
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 52e5194e6236..aa8ed91d382f 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -12,11 +12,11 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/Parser.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/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
@@ -37,26 +37,6 @@ public:
return false;
}
};
-
-/// \brief RAIIObject to destroy the contents of a SmallVector of
-/// TemplateIdAnnotation pointers and clear the vector.
-class DestroyTemplateIdAnnotationsRAIIObj {
- SmallVectorImpl<TemplateIdAnnotation *> &Container;
-
-public:
- DestroyTemplateIdAnnotationsRAIIObj(
- SmallVectorImpl<TemplateIdAnnotation *> &Container)
- : Container(Container) {}
-
- ~DestroyTemplateIdAnnotationsRAIIObj() {
- for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I =
- Container.begin(),
- E = Container.end();
- I != E; ++I)
- (*I)->Destroy();
- Container.clear();
- }
-};
} // end anonymous namespace
IdentifierInfo *Parser::getSEHExceptKeyword() {
@@ -231,6 +211,21 @@ void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) {
<< FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc));
}
+bool Parser::expectIdentifier() {
+ if (Tok.is(tok::identifier))
+ return false;
+ if (const auto *II = Tok.getIdentifierInfo()) {
+ if (II->isCPlusPlusKeyword(getLangOpts())) {
+ Diag(Tok, diag::err_expected_token_instead_of_objcxx_keyword)
+ << tok::identifier << Tok.getIdentifierInfo();
+ // Objective-C++: Recover by treating this keyword as a valid identifier.
+ return false;
+ }
+ }
+ Diag(Tok, diag::err_expected) << tok::identifier;
+ return true;
+}
+
//===----------------------------------------------------------------------===//
// Error recovery.
//===----------------------------------------------------------------------===//
@@ -493,6 +488,8 @@ void Parser::Initialize() {
Ident_strict = nullptr;
Ident_replacement = nullptr;
+ Ident_language = Ident_defined_in = Ident_generated_declaration = nullptr;
+
Ident__except = nullptr;
Ident__exception_code = Ident__exception_info = nullptr;
@@ -688,6 +685,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
case tok::annot_pragma_fp_contract:
HandlePragmaFPContract();
return nullptr;
+ case tok::annot_pragma_fp:
+ HandlePragmaFP();
+ break;
case tok::annot_pragma_opencl_extension:
HandlePragmaOpenCLExtension();
return nullptr;
@@ -1701,6 +1701,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS,
TemplateId->TemplateKWLoc,
TemplateId->Template,
+ TemplateId->Name,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
@@ -1742,7 +1743,8 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS,
*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), &SS,
false, NextToken().is(tok::period), nullptr,
/*IsCtorOrDtorName=*/false,
- /*NonTrivialTypeSourceInfo*/ true)) {
+ /*NonTrivialTypeSourceInfo*/ true,
+ /*IsClassTemplateDeductionContext*/GreaterThanIsOperator)) {
SourceLocation BeginLoc = Tok.getLocation();
if (SS.isNotEmpty()) // it was a C++ qualified type name.
BeginLoc = SS.getBeginLoc();
@@ -1964,8 +1966,10 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) {
// Parse the unqualified-id.
SourceLocation TemplateKWLoc; // FIXME: parsed, but unused.
- if (ParseUnqualifiedId(Result.SS, false, true, true, nullptr, TemplateKWLoc,
- Result.Name)) {
+ if (ParseUnqualifiedId(
+ Result.SS, /*EnteringContext*/false, /*AllowDestructorName*/true,
+ /*AllowConstructorName*/true, /*AllowDeductionGuide*/false, nullptr,
+ TemplateKWLoc, Result.Name)) {
T.skipToEnd();
return true;
}
diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h
deleted file mode 100644
index 36d87ebd8aca..000000000000
--- a/lib/Parse/RAIIObjectsForParser.h
+++ /dev/null
@@ -1,447 +0,0 @@
-//===--- RAIIObjectsForParser.h - RAII helpers for the parser ---*- 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 and implements the some simple RAII objects that are used
-// by the parser to manage bits in recursion.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H
-#define LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H
-
-#include "clang/Parse/ParseDiagnostic.h"
-#include "clang/Parse/Parser.h"
-#include "clang/Sema/DelayedDiagnostic.h"
-#include "clang/Sema/Sema.h"
-
-namespace clang {
- // TODO: move ParsingClassDefinition here.
- // TODO: move TentativeParsingAction here.
-
- /// \brief A RAII object used to temporarily suppress access-like
- /// checking. Access-like checks are those associated with
- /// controlling the use of a declaration, like C++ access control
- /// errors and deprecation warnings. They are contextually
- /// dependent, in that they can only be resolved with full
- /// information about what's being declared. They are also
- /// suppressed in certain contexts, like the template arguments of
- /// an explicit instantiation. However, those suppression contexts
- /// cannot necessarily be fully determined in advance; for
- /// example, something starting like this:
- /// template <> class std::vector<A::PrivateType>
- /// might be the entirety of an explicit instantiation:
- /// template <> class std::vector<A::PrivateType>;
- /// or just an elaborated type specifier:
- /// template <> class std::vector<A::PrivateType> make_vector<>();
- /// Therefore this class collects all the diagnostics and permits
- /// them to be re-delayed in a new context.
- class SuppressAccessChecks {
- Sema &S;
- sema::DelayedDiagnosticPool DiagnosticPool;
- Sema::ParsingDeclState State;
- bool Active;
-
- public:
- /// Begin suppressing access-like checks
- SuppressAccessChecks(Parser &P, bool activate = true)
- : S(P.getActions()), DiagnosticPool(nullptr) {
- if (activate) {
- State = S.PushParsingDeclaration(DiagnosticPool);
- Active = true;
- } else {
- Active = false;
- }
- }
- SuppressAccessChecks(SuppressAccessChecks &&Other)
- : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)),
- State(Other.State), Active(Other.Active) {
- Other.Active = false;
- }
- void operator=(SuppressAccessChecks &&Other) = delete;
-
- void done() {
- assert(Active && "trying to end an inactive suppression");
- S.PopParsingDeclaration(State, nullptr);
- Active = false;
- }
-
- void redelay() {
- assert(!Active && "redelaying without having ended first");
- if (!DiagnosticPool.pool_empty())
- S.redelayDiagnostics(DiagnosticPool);
- assert(DiagnosticPool.pool_empty());
- }
-
- ~SuppressAccessChecks() {
- if (Active) done();
- }
- };
-
- /// \brief RAII object used to inform the actions that we're
- /// currently parsing a declaration. This is active when parsing a
- /// variable's initializer, but not when parsing the body of a
- /// class or function definition.
- class ParsingDeclRAIIObject {
- Sema &Actions;
- sema::DelayedDiagnosticPool DiagnosticPool;
- Sema::ParsingDeclState State;
- bool Popped;
-
- ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) = delete;
- void operator=(const ParsingDeclRAIIObject &) = delete;
-
- public:
- enum NoParent_t { NoParent };
- ParsingDeclRAIIObject(Parser &P, NoParent_t _)
- : Actions(P.getActions()), DiagnosticPool(nullptr) {
- push();
- }
-
- /// Creates a RAII object whose pool is optionally parented by another.
- ParsingDeclRAIIObject(Parser &P,
- const sema::DelayedDiagnosticPool *parentPool)
- : Actions(P.getActions()), DiagnosticPool(parentPool) {
- push();
- }
-
- /// Creates a RAII object and, optionally, initialize its
- /// diagnostics pool by stealing the diagnostics from another
- /// RAII object (which is assumed to be the current top pool).
- ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
- : Actions(P.getActions()),
- DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) {
- if (other) {
- DiagnosticPool.steal(other->DiagnosticPool);
- other->abort();
- }
- push();
- }
-
- ~ParsingDeclRAIIObject() {
- abort();
- }
-
- sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() {
- return DiagnosticPool;
- }
- const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
- return DiagnosticPool;
- }
-
- /// Resets the RAII object for a new declaration.
- void reset() {
- abort();
- push();
- }
-
- /// Signals that the context was completed without an appropriate
- /// declaration being parsed.
- void abort() {
- pop(nullptr);
- }
-
- void complete(Decl *D) {
- assert(!Popped && "ParsingDeclaration has already been popped!");
- pop(D);
- }
-
- /// Unregister this object from Sema, but remember all the
- /// diagnostics that were emitted into it.
- void abortAndRemember() {
- pop(nullptr);
- }
-
- private:
- void push() {
- State = Actions.PushParsingDeclaration(DiagnosticPool);
- Popped = false;
- }
-
- void pop(Decl *D) {
- if (!Popped) {
- Actions.PopParsingDeclaration(State, D);
- Popped = true;
- }
- }
- };
-
- /// A class for parsing a DeclSpec.
- class ParsingDeclSpec : public DeclSpec {
- ParsingDeclRAIIObject ParsingRAII;
-
- public:
- ParsingDeclSpec(Parser &P)
- : DeclSpec(P.getAttrFactory()),
- ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
- ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
- : DeclSpec(P.getAttrFactory()),
- ParsingRAII(P, RAII) {}
-
- const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
- return ParsingRAII.getDelayedDiagnosticPool();
- }
-
- void complete(Decl *D) {
- ParsingRAII.complete(D);
- }
-
- void abort() {
- ParsingRAII.abort();
- }
- };
-
- /// A class for parsing a declarator.
- class ParsingDeclarator : public Declarator {
- ParsingDeclRAIIObject ParsingRAII;
-
- public:
- ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
- : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
- }
-
- const ParsingDeclSpec &getDeclSpec() const {
- return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
- }
-
- ParsingDeclSpec &getMutableDeclSpec() const {
- return const_cast<ParsingDeclSpec&>(getDeclSpec());
- }
-
- void clear() {
- Declarator::clear();
- ParsingRAII.reset();
- }
-
- void complete(Decl *D) {
- ParsingRAII.complete(D);
- }
- };
-
- /// A class for parsing a field declarator.
- class ParsingFieldDeclarator : public FieldDeclarator {
- ParsingDeclRAIIObject ParsingRAII;
-
- public:
- ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS)
- : FieldDeclarator(DS), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
- }
-
- const ParsingDeclSpec &getDeclSpec() const {
- return static_cast<const ParsingDeclSpec&>(D.getDeclSpec());
- }
-
- ParsingDeclSpec &getMutableDeclSpec() const {
- return const_cast<ParsingDeclSpec&>(getDeclSpec());
- }
-
- void complete(Decl *D) {
- ParsingRAII.complete(D);
- }
- };
-
- /// ExtensionRAIIObject - This saves the state of extension warnings when
- /// constructed and disables them. When destructed, it restores them back to
- /// the way they used to be. This is used to handle __extension__ in the
- /// parser.
- class ExtensionRAIIObject {
- ExtensionRAIIObject(const ExtensionRAIIObject &) = delete;
- void operator=(const ExtensionRAIIObject &) = delete;
-
- DiagnosticsEngine &Diags;
- public:
- ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
- Diags.IncrementAllExtensionsSilenced();
- }
-
- ~ExtensionRAIIObject() {
- Diags.DecrementAllExtensionsSilenced();
- }
- };
-
- /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
- /// restores it when destroyed. This says that "foo:" should not be
- /// considered a possible typo for "foo::" for error recovery purposes.
- class ColonProtectionRAIIObject {
- Parser &P;
- bool OldVal;
- public:
- ColonProtectionRAIIObject(Parser &p, bool Value = true)
- : P(p), OldVal(P.ColonIsSacred) {
- P.ColonIsSacred = Value;
- }
-
- /// restore - This can be used to restore the state early, before the dtor
- /// is run.
- void restore() {
- P.ColonIsSacred = OldVal;
- }
-
- ~ColonProtectionRAIIObject() {
- restore();
- }
- };
-
- /// \brief RAII object that makes '>' behave either as an operator
- /// or as the closing angle bracket for a template argument list.
- class GreaterThanIsOperatorScope {
- bool &GreaterThanIsOperator;
- bool OldGreaterThanIsOperator;
- public:
- GreaterThanIsOperatorScope(bool &GTIO, bool Val)
- : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
- GreaterThanIsOperator = Val;
- }
-
- ~GreaterThanIsOperatorScope() {
- GreaterThanIsOperator = OldGreaterThanIsOperator;
- }
- };
-
- class InMessageExpressionRAIIObject {
- bool &InMessageExpression;
- bool OldValue;
-
- public:
- InMessageExpressionRAIIObject(Parser &P, bool Value)
- : InMessageExpression(P.InMessageExpression),
- OldValue(P.InMessageExpression) {
- InMessageExpression = Value;
- }
-
- ~InMessageExpressionRAIIObject() {
- InMessageExpression = OldValue;
- }
- };
-
- /// \brief RAII object that makes sure paren/bracket/brace count is correct
- /// after declaration/statement parsing, even when there's a parsing error.
- class ParenBraceBracketBalancer {
- Parser &P;
- unsigned short ParenCount, BracketCount, BraceCount;
- public:
- ParenBraceBracketBalancer(Parser &p)
- : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
- BraceCount(p.BraceCount) { }
-
- ~ParenBraceBracketBalancer() {
- P.ParenCount = ParenCount;
- P.BracketCount = BracketCount;
- P.BraceCount = BraceCount;
- }
- };
-
- class PoisonSEHIdentifiersRAIIObject {
- PoisonIdentifierRAIIObject Ident_AbnormalTermination;
- PoisonIdentifierRAIIObject Ident_GetExceptionCode;
- PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
- PoisonIdentifierRAIIObject Ident__abnormal_termination;
- PoisonIdentifierRAIIObject Ident__exception_code;
- PoisonIdentifierRAIIObject Ident__exception_info;
- PoisonIdentifierRAIIObject Ident___abnormal_termination;
- PoisonIdentifierRAIIObject Ident___exception_code;
- PoisonIdentifierRAIIObject Ident___exception_info;
- public:
- PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue)
- : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
- Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
- Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
- Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
- Ident__exception_code(Self.Ident__exception_code, NewValue),
- Ident__exception_info(Self.Ident__exception_info, NewValue),
- Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
- Ident___exception_code(Self.Ident___exception_code, NewValue),
- Ident___exception_info(Self.Ident___exception_info, NewValue) {
- }
- };
-
- /// \brief RAII class that helps handle the parsing of an open/close delimiter
- /// pair, such as braces { ... } or parentheses ( ... ).
- class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
- Parser& P;
- tok::TokenKind Kind, Close, FinalToken;
- SourceLocation (Parser::*Consumer)();
- SourceLocation LOpen, LClose;
-
- unsigned short &getDepth() {
- switch (Kind) {
- case tok::l_brace: return P.BraceCount;
- case tok::l_square: return P.BracketCount;
- case tok::l_paren: return P.ParenCount;
- default: llvm_unreachable("Wrong token kind");
- }
- }
-
- enum { MaxDepth = 256 };
-
- bool diagnoseOverflow();
- bool diagnoseMissingClose();
-
- public:
- BalancedDelimiterTracker(Parser& p, tok::TokenKind k,
- tok::TokenKind FinalToken = tok::semi)
- : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
- P(p), Kind(k), FinalToken(FinalToken)
- {
- switch (Kind) {
- default: llvm_unreachable("Unexpected balanced token");
- case tok::l_brace:
- Close = tok::r_brace;
- Consumer = &Parser::ConsumeBrace;
- break;
- case tok::l_paren:
- Close = tok::r_paren;
- Consumer = &Parser::ConsumeParen;
- break;
-
- case tok::l_square:
- Close = tok::r_square;
- Consumer = &Parser::ConsumeBracket;
- break;
- }
- }
-
- SourceLocation getOpenLocation() const { return LOpen; }
- SourceLocation getCloseLocation() const { return LClose; }
- SourceRange getRange() const { return SourceRange(LOpen, LClose); }
-
- bool consumeOpen() {
- if (!P.Tok.is(Kind))
- return true;
-
- if (getDepth() < P.getLangOpts().BracketDepth) {
- LOpen = (P.*Consumer)();
- return false;
- }
-
- return diagnoseOverflow();
- }
-
- bool expectAndConsume(unsigned DiagID = diag::err_expected,
- const char *Msg = "",
- tok::TokenKind SkipToTok = tok::unknown);
- bool consumeClose() {
- if (P.Tok.is(Close)) {
- LClose = (P.*Consumer)();
- return false;
- } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
- SourceLocation SemiLoc = P.ConsumeToken();
- P.Diag(SemiLoc, diag::err_unexpected_semi)
- << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
- LClose = (P.*Consumer)();
- return false;
- }
-
- return diagnoseMissingClose();
- }
- void skipToEnd();
- };
-
-} // end namespace clang
-
-#endif