aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Parse/ParseExprCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/ParseExprCXX.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Parse/ParseExprCXX.cpp193
1 files changed, 157 insertions, 36 deletions
diff --git a/contrib/llvm-project/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm-project/clang/lib/Parse/ParseExprCXX.cpp
index d61f414406f0..1d364f77a814 100644
--- a/contrib/llvm-project/clang/lib/Parse/ParseExprCXX.cpp
+++ b/contrib/llvm-project/clang/lib/Parse/ParseExprCXX.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Parse/ParseDiagnostic.h"
@@ -23,6 +24,7 @@
#include "clang/Sema/EnterExpressionEvaluationContext.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
+#include "clang/Sema/SemaCodeCompletion.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <numeric>
@@ -157,7 +159,8 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType,
bool Parser::ParseOptionalCXXScopeSpecifier(
CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors,
bool EnteringContext, bool *MayBePseudoDestructor, bool IsTypename,
- IdentifierInfo **LastII, bool OnlyNamespace, bool InUsingDeclaration) {
+ const IdentifierInfo **LastII, bool OnlyNamespace,
+ bool InUsingDeclaration) {
assert(getLangOpts().CPlusPlus &&
"Call sites of this function should be guarded by checking for C++");
@@ -233,6 +236,34 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
HasScopeSpecifier = true;
}
+ else if (!HasScopeSpecifier && Tok.is(tok::identifier) &&
+ GetLookAheadToken(1).is(tok::ellipsis) &&
+ GetLookAheadToken(2).is(tok::l_square)) {
+ SourceLocation Start = Tok.getLocation();
+ DeclSpec DS(AttrFactory);
+ SourceLocation CCLoc;
+ SourceLocation EndLoc = ParsePackIndexingType(DS);
+ if (DS.getTypeSpecType() == DeclSpec::TST_error)
+ return false;
+
+ QualType Type = Actions.ActOnPackIndexingType(
+ DS.getRepAsType().get(), DS.getPackIndexingExpr(), DS.getBeginLoc(),
+ DS.getEllipsisLoc());
+
+ if (Type.isNull())
+ return false;
+
+ if (!TryConsumeToken(tok::coloncolon, CCLoc)) {
+ AnnotateExistingIndexedTypeNamePack(ParsedType::make(Type), Start,
+ EndLoc);
+ return false;
+ }
+ if (Actions.ActOnCXXNestedNameSpecifierIndexedPack(SS, DS, CCLoc,
+ std::move(Type)))
+ SS.SetInvalid(SourceRange(Start, CCLoc));
+ HasScopeSpecifier = true;
+ }
+
// Preferred type might change when parsing qualifiers, we need the original.
auto SavedType = PreferredType;
while (true) {
@@ -241,9 +272,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
cutOffParsing();
// Code completion for a nested-name-specifier, where the code
// completion token follows the '::'.
- Actions.CodeCompleteQualifiedId(getCurScope(), SS, EnteringContext,
- InUsingDeclaration, ObjectType.get(),
- SavedType.get(SS.getBeginLoc()));
+ Actions.CodeCompletion().CodeCompleteQualifiedId(
+ getCurScope(), SS, EnteringContext, InUsingDeclaration,
+ ObjectType.get(), SavedType.get(SS.getBeginLoc()));
// Include code completion token into the range of the scope otherwise
// when we try to annotate the scope tokens the dangling code completion
// token will cause assertion in
@@ -378,6 +409,20 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
continue;
}
+ switch (Tok.getKind()) {
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
+ if (!NextToken().is(tok::l_paren)) {
+ Tok.setKind(tok::identifier);
+ Diag(Tok, diag::ext_keyword_as_ident)
+ << Tok.getIdentifierInfo()->getName() << 0;
+ continue;
+ }
+ [[fallthrough]];
+ default:
+ break;
+ }
+
// The rest of the nested-name-specifier possibilities start with
// tok::identifier.
if (Tok.isNot(tok::identifier))
@@ -617,11 +662,38 @@ ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS,
break;
}
+ // Might be a pack index expression!
+ E = tryParseCXXPackIndexingExpression(E);
+
if (!E.isInvalid() && !E.isUnset() && Tok.is(tok::less))
checkPotentialAngleBracket(E);
return E;
}
+ExprResult Parser::ParseCXXPackIndexingExpression(ExprResult PackIdExpression) {
+ assert(Tok.is(tok::ellipsis) && NextToken().is(tok::l_square) &&
+ "expected ...[");
+ SourceLocation EllipsisLoc = ConsumeToken();
+ BalancedDelimiterTracker T(*this, tok::l_square);
+ T.consumeOpen();
+ ExprResult IndexExpr = ParseConstantExpression();
+ if (T.consumeClose() || IndexExpr.isInvalid())
+ return ExprError();
+ return Actions.ActOnPackIndexingExpr(getCurScope(), PackIdExpression.get(),
+ EllipsisLoc, T.getOpenLocation(),
+ IndexExpr.get(), T.getCloseLocation());
+}
+
+ExprResult
+Parser::tryParseCXXPackIndexingExpression(ExprResult PackIdExpression) {
+ ExprResult E = PackIdExpression;
+ if (!PackIdExpression.isInvalid() && !PackIdExpression.isUnset() &&
+ Tok.is(tok::ellipsis) && NextToken().is(tok::l_square)) {
+ E = ParseCXXPackIndexingExpression(E);
+ }
+ return E;
+}
+
/// ParseCXXIdExpression - Handle id-expression.
///
/// id-expression:
@@ -751,9 +823,8 @@ ExprResult Parser::ParseLambdaExpression() {
///
/// If we are not looking at a lambda expression, returns ExprError().
ExprResult Parser::TryParseLambdaExpression() {
- assert(getLangOpts().CPlusPlus11
- && Tok.is(tok::l_square)
- && "Not at the start of a possible lambda expression.");
+ assert(getLangOpts().CPlusPlus && Tok.is(tok::l_square) &&
+ "Not at the start of a possible lambda expression.");
const Token Next = NextToken();
if (Next.is(tok::eof)) // Nothing else to lookup here...
@@ -885,8 +956,9 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
if (Tok.is(tok::code_completion) &&
!(getLangOpts().ObjC && Tentative)) {
cutOffParsing();
- Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
- /*AfterAmpersand=*/false);
+ Actions.CodeCompletion().CodeCompleteLambdaIntroducer(
+ getCurScope(), Intro,
+ /*AfterAmpersand=*/false);
break;
}
@@ -902,10 +974,11 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// If we're in Objective-C++ and we have a bare '[', then this is more
// likely to be a message receiver.
if (getLangOpts().ObjC && Tentative && First)
- Actions.CodeCompleteObjCMessageReceiver(getCurScope());
+ Actions.CodeCompletion().CodeCompleteObjCMessageReceiver(getCurScope());
else
- Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
- /*AfterAmpersand=*/false);
+ Actions.CodeCompletion().CodeCompleteLambdaIntroducer(
+ getCurScope(), Intro,
+ /*AfterAmpersand=*/false);
break;
}
@@ -951,8 +1024,9 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
if (Tok.is(tok::code_completion)) {
cutOffParsing();
- Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
- /*AfterAmpersand=*/true);
+ Actions.CodeCompletion().CodeCompleteLambdaIntroducer(
+ getCurScope(), Intro,
+ /*AfterAmpersand=*/true);
break;
}
}
@@ -1271,7 +1345,9 @@ static void DiagnoseStaticSpecifierRestrictions(Parser &P,
ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
LambdaIntroducer &Intro) {
SourceLocation LambdaBeginLoc = Intro.Range.getBegin();
- Diag(LambdaBeginLoc, diag::warn_cxx98_compat_lambda);
+ Diag(LambdaBeginLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_lambda
+ : diag::ext_lambda);
PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc,
"lambda expression parsing");
@@ -1330,6 +1406,16 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
Diag(RAngleLoc,
diag::err_lambda_template_parameter_list_empty);
} else {
+ // We increase the template depth before recursing into a requires-clause.
+ //
+ // This depth is used for setting up a LambdaScopeInfo (in
+ // Sema::RecordParsingTemplateParameterDepth), which is used later when
+ // inventing template parameters in InventTemplateParameter.
+ //
+ // This way, abbreviated generic lambdas could have different template
+ // depths, avoiding substitution into the wrong template parameters during
+ // constraint satisfaction check.
+ ++CurTemplateDepthTracker;
ExprResult RequiresClause;
if (TryConsumeToken(tok::kw_requires)) {
RequiresClause =
@@ -1341,7 +1427,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
Actions.ActOnLambdaExplicitTemplateParameterList(
Intro, LAngleLoc, TemplateParams, RAngleLoc, RequiresClause);
- ++CurTemplateDepthTracker;
}
}
@@ -1496,7 +1581,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
TrailingReturnTypeLoc, &DS),
std::move(Attributes), DeclEndLoc);
- Actions.ActOnLambdaClosureQualifiers(Intro, MutableLoc);
+ // We have called ActOnLambdaClosureQualifiers for parentheses-less cases
+ // above.
+ if (HasParentheses)
+ Actions.ActOnLambdaClosureQualifiers(Intro, MutableLoc);
if (HasParentheses && Tok.is(tok::kw_requires))
ParseTrailingRequiresClause(D);
@@ -1810,6 +1898,15 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
return ExprError();
}
+ // pack-index-specifier
+ if (GetLookAheadToken(1).is(tok::ellipsis) &&
+ GetLookAheadToken(2).is(tok::l_square)) {
+ DeclSpec DS(AttrFactory);
+ ParsePackIndexingType(DS);
+ return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind,
+ TildeLoc, DS);
+ }
+
// Parse the second type.
UnqualifiedId SecondTypeName;
IdentifierInfo *Name = Tok.getIdentifierInfo();
@@ -1942,9 +2039,10 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
auto RunSignatureHelp = [&]() {
QualType PreferredType;
if (TypeRep)
- PreferredType = Actions.ProduceConstructorSignatureHelp(
- TypeRep.get()->getCanonicalTypeInternal(), DS.getEndLoc(), Exprs,
- T.getOpenLocation(), /*Braced=*/false);
+ PreferredType =
+ Actions.CodeCompletion().ProduceConstructorSignatureHelp(
+ TypeRep.get()->getCanonicalTypeInternal(), DS.getEndLoc(),
+ Exprs, T.getOpenLocation(), /*Braced=*/false);
CalledSignatureHelp = true;
return PreferredType;
};
@@ -2051,7 +2149,8 @@ Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc,
if (Tok.is(tok::code_completion)) {
cutOffParsing();
- Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition);
+ Actions.CodeCompletion().CodeCompleteOrdinaryName(
+ getCurScope(), SemaCodeCompletion::PCC_Condition);
return Sema::ConditionError();
}
@@ -2253,7 +2352,6 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
getTypeAnnotation(Tok), Policy);
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
ConsumeAnnotationToken();
-
DS.Finish(Actions, Policy);
return;
}
@@ -2364,6 +2462,10 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
DS.SetRangeEnd(ParseDecltypeSpecifier(DS));
return DS.Finish(Actions, Policy);
+ case tok::annot_pack_indexing_type:
+ DS.SetRangeEnd(ParsePackIndexingType(DS));
+ return DS.Finish(Actions, Policy);
+
// GNU typeof support.
case tok::kw_typeof:
ParseTypeofSpecifier(DS);
@@ -2549,7 +2651,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(
// UnqualifiedId.
// FIXME: Store name for literal operator too.
- IdentifierInfo *TemplateII =
+ const IdentifierInfo *TemplateII =
Id.getKind() == UnqualifiedIdKind::IK_Identifier ? Id.Identifier
: nullptr;
OverloadedOperatorKind OpKind =
@@ -2700,7 +2802,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
// Don't try to parse any further.
cutOffParsing();
// Code completion for the operator name.
- Actions.CodeCompleteOperatorName(getCurScope());
+ Actions.CodeCompletion().CodeCompleteOperatorName(getCurScope());
return true;
}
@@ -2928,13 +3030,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
SS, ObjectType, ObjectHadErrors,
TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc,
EnteringContext, Result, TemplateSpecified);
- else if (TemplateSpecified &&
- Actions.ActOnTemplateName(
- getCurScope(), SS, *TemplateKWLoc, Result, ObjectType,
- EnteringContext, Template,
- /*AllowInjectedClassName*/ true) == TNK_Non_template)
- return true;
+ if (TemplateSpecified) {
+ TemplateNameKind TNK =
+ Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result,
+ ObjectType, EnteringContext, Template,
+ /*AllowInjectedClassName=*/true);
+ if (TNK == TNK_Non_template)
+ return true;
+
+ // C++2c [tem.names]p6
+ // A name prefixed by the keyword template shall be followed by a template
+ // argument list or refer to a class template or an alias template.
+ if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name ||
+ TNK == TNK_Var_template) &&
+ !Tok.is(tok::less))
+ Diag(IdLoc, diag::missing_template_arg_list_after_template_kw);
+ }
return false;
}
@@ -3258,10 +3370,12 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
// the passing DeclaratorInfo is valid, e.g. running SignatureHelp on
// `new decltype(invalid) (^)`.
if (TypeRep)
- PreferredType = Actions.ProduceConstructorSignatureHelp(
- TypeRep.get()->getCanonicalTypeInternal(),
- DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen,
- /*Braced=*/false);
+ PreferredType =
+ Actions.CodeCompletion().ProduceConstructorSignatureHelp(
+ TypeRep.get()->getCanonicalTypeInternal(),
+ DeclaratorInfo.getEndLoc(), ConstructorArgs,
+ ConstructorLParen,
+ /*Braced=*/false);
CalledSignatureHelp = true;
return PreferredType;
};
@@ -3832,7 +3946,10 @@ ExprResult Parser::ParseTypeTrait() {
SmallVector<ParsedType, 2> Args;
do {
// Parse the next type.
- TypeResult Ty = ParseTypeName();
+ TypeResult Ty = ParseTypeName(/*SourceRange=*/nullptr,
+ getLangOpts().CPlusPlus
+ ? DeclaratorContext::TemplateTypeArg
+ : DeclaratorContext::TypeName);
if (Ty.isInvalid()) {
Parens.skipToEnd();
return ExprError();
@@ -3874,7 +3991,8 @@ ExprResult Parser::ParseArrayTypeTrait() {
if (T.expectAndConsume())
return ExprError();
- TypeResult Ty = ParseTypeName();
+ TypeResult Ty = ParseTypeName(/*SourceRange=*/nullptr,
+ DeclaratorContext::TemplateTypeArg);
if (Ty.isInvalid()) {
SkipUntil(tok::comma, StopAtSemi);
SkipUntil(tok::r_paren, StopAtSemi);
@@ -3896,6 +4014,9 @@ ExprResult Parser::ParseArrayTypeTrait() {
ExprResult DimExpr = ParseExpression();
T.consumeClose();
+ if (DimExpr.isInvalid())
+ return ExprError();
+
return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), DimExpr.get(),
T.getCloseLocation());
}