diff options
Diffstat (limited to 'lib/Parse/ParseExprCXX.cpp')
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 91 |
1 files changed, 54 insertions, 37 deletions
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; } |