aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Parse
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse')
-rw-r--r--clang/lib/Parse/ParseDecl.cpp18
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp2
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp22
-rw-r--r--clang/lib/Parse/ParseInit.cpp23
-rw-r--r--clang/lib/Parse/ParseOpenMP.cpp155
-rw-r--r--clang/lib/Parse/ParseStmt.cpp16
-rw-r--r--clang/lib/Parse/ParseTentative.cpp2
-rw-r--r--clang/lib/Parse/Parser.cpp41
8 files changed, 212 insertions, 67 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index e4b158e..8688ccf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2613,7 +2613,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
}
PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl);
- ExprResult Init = ParseInitializer();
+ ExprResult Init = ParseInitializer(ThisDecl);
// If this is the only decl in (possibly) range based for statement,
// our best guess is that the user meant ':' instead of '='.
@@ -4248,6 +4248,13 @@ void Parser::ParseDeclarationSpecifiers(
// type-specifier
case tok::kw_short:
+ if (!getLangOpts().NativeInt16Type) {
+ Diag(Tok, diag::err_unknown_typename) << Tok.getName();
+ DS.SetTypeSpecError();
+ DS.SetRangeEnd(Tok.getLocation());
+ ConsumeToken();
+ goto DoneWithDeclSpec;
+ }
isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::Short, Loc, PrevSpec,
DiagID, Policy);
break;
@@ -5363,8 +5370,13 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl,
T.consumeOpen();
// C does not allow an empty enumerator-list, C++ does [dcl.enum].
- if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus)
- Diag(Tok, diag::err_empty_enum);
+ if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus) {
+ if (getLangOpts().MicrosoftExt)
+ Diag(T.getOpenLocation(), diag::ext_ms_c_empty_enum_type)
+ << SourceRange(T.getOpenLocation(), Tok.getLocation());
+ else
+ Diag(Tok, diag::err_empty_enum);
+ }
SmallVector<Decl *, 32> EnumConstantDecls;
SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags;
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index b96968d..d8ed7e3 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -3359,7 +3359,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
Diag(Tok, diag::err_ms_property_initializer) << PD;
return ExprError();
}
- return ParseInitializer();
+ return ParseInitializer(D);
}
void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc,
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 74f87a8..7a5d28c 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -772,9 +772,11 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// Produce a diagnostic if we're not tentatively parsing; otherwise track
// that our parse has failed.
- auto Invalid = [&](llvm::function_ref<void()> Action) {
+ auto Result = [&](llvm::function_ref<void()> Action,
+ LambdaIntroducerTentativeParse State =
+ LambdaIntroducerTentativeParse::Invalid) {
if (Tentative) {
- *Tentative = LambdaIntroducerTentativeParse::Invalid;
+ *Tentative = State;
return false;
}
Action();
@@ -824,7 +826,7 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
break;
}
- return Invalid([&] {
+ return Result([&] {
Diag(Tok.getLocation(), diag::err_expected_comma_or_rsquare);
});
}
@@ -861,7 +863,7 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
ConsumeToken();
Kind = LCK_StarThis;
} else {
- return Invalid([&] {
+ return Result([&] {
Diag(Tok.getLocation(), diag::err_expected_star_this_capture);
});
}
@@ -875,8 +877,9 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// or the start of a capture (in the "&" case) with the rest of the
// capture missing. Both are an error but a misplaced capture-default
// is more likely if we don't already have a capture default.
- return Invalid(
- [&] { Diag(Tok.getLocation(), diag::err_capture_default_first); });
+ return Result(
+ [&] { Diag(Tok.getLocation(), diag::err_capture_default_first); },
+ LambdaIntroducerTentativeParse::Incomplete);
} else {
TryConsumeToken(tok::ellipsis, EllipsisLocs[0]);
@@ -899,14 +902,13 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
Id = Tok.getIdentifierInfo();
Loc = ConsumeToken();
} else if (Tok.is(tok::kw_this)) {
- return Invalid([&] {
+ return Result([&] {
// FIXME: Suggest a fixit here.
Diag(Tok.getLocation(), diag::err_this_captured_by_reference);
});
} else {
- return Invalid([&] {
- Diag(Tok.getLocation(), diag::err_expected_capture);
- });
+ return Result(
+ [&] { Diag(Tok.getLocation(), diag::err_expected_capture); });
}
TryConsumeToken(tok::ellipsis, EllipsisLocs[2]);
diff --git a/clang/lib/Parse/ParseInit.cpp b/clang/lib/Parse/ParseInit.cpp
index a3be374..0e86c4c 100644
--- a/clang/lib/Parse/ParseInit.cpp
+++ b/clang/lib/Parse/ParseInit.cpp
@@ -581,3 +581,26 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
return !trailingComma;
}
+
+ExprResult Parser::ParseInitializer(Decl *DeclForInitializer) {
+ // Set DeclForInitializer for file-scope variables.
+ // For constexpr references, set it to suppress runtime warnings.
+ // For non-constexpr references, don't set it to avoid evaluation issues
+ // with self-referencing initializers. Local variables (including local
+ // constexpr) should emit runtime warnings.
+ if (DeclForInitializer && !Actions.ExprEvalContexts.empty()) {
+ if (auto *VD = dyn_cast<VarDecl>(DeclForInitializer);
+ VD && VD->isFileVarDecl() &&
+ (!VD->getType()->isReferenceType() || VD->isConstexpr()))
+ Actions.ExprEvalContexts.back().DeclForInitializer = VD;
+ }
+
+ ExprResult init;
+ if (Tok.isNot(tok::l_brace)) {
+ init = ParseAssignmentExpression();
+ } else {
+ init = ParseBraceInitializer();
+ }
+
+ return init;
+}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 25199c7..15c3f75 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -339,7 +339,7 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
}
PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
- ExprResult Init = ParseInitializer();
+ ExprResult Init = ParseInitializer(OmpPrivParm);
if (Init.isInvalid()) {
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
@@ -3178,6 +3178,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_align:
case OMPC_message:
case OMPC_ompx_dyn_cgroup_mem:
+ case OMPC_dyn_groupprivate:
// OpenMP [2.5, Restrictions]
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
@@ -3216,11 +3217,12 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
Clause = ParseOpenMPClause(CKind, WrongDirective);
else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks ||
- CKind == OMPC_num_threads)
+ CKind == OMPC_num_threads || CKind == OMPC_dyn_groupprivate)
Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
else
Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
break;
+ case OMPC_threadset:
case OMPC_fail:
case OMPC_proc_bind:
case OMPC_atomic_default_mem_order:
@@ -4008,6 +4010,83 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
Arg.push_back(OMPC_GRAINSIZE_unknown);
KLoc.emplace_back();
}
+ } else if (Kind == OMPC_dyn_groupprivate) {
+ enum { SimpleModifier, ComplexModifier, NumberOfModifiers };
+ Arg.resize(NumberOfModifiers);
+ KLoc.resize(NumberOfModifiers);
+ Arg[SimpleModifier] = OMPC_DYN_GROUPPRIVATE_unknown;
+ Arg[ComplexModifier] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown;
+
+ auto ConsumeModifier = [&]() {
+ unsigned Type = NumberOfModifiers;
+ unsigned Modifier;
+ SourceLocation Loc;
+ if (!Tok.isAnnotation() && PP.getSpelling(Tok) == "fallback" &&
+ NextToken().is(tok::l_paren)) {
+ ConsumeToken();
+ BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
+ ParenT.consumeOpen();
+
+ Modifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
+ if (Modifier <= OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown ||
+ Modifier >= OMPC_DYN_GROUPPRIVATE_FALLBACK_last) {
+ Diag(Tok.getLocation(), diag::err_expected)
+ << "'abort', 'null' or 'default_mem' in fallback modifier";
+ SkipUntil(tok::r_paren);
+ return std::make_tuple(Type, Modifier, Loc);
+ }
+ Type = ComplexModifier;
+ Loc = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ ParenT.consumeClose();
+ } else {
+ Modifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
+ if (Modifier < OMPC_DYN_GROUPPRIVATE_unknown) {
+ Type = SimpleModifier;
+ Loc = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ }
+ }
+ return std::make_tuple(Type, Modifier, Loc);
+ };
+
+ auto SaveModifier = [&](unsigned Type, unsigned Modifier,
+ SourceLocation Loc) {
+ assert(Type < NumberOfModifiers && "Unexpected modifier type");
+ if (!KLoc[Type].isValid()) {
+ Arg[Type] = Modifier;
+ KLoc[Type] = Loc;
+ } else {
+ Diag(Loc, diag::err_omp_incompatible_dyn_groupprivate_modifier)
+ << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Modifier)
+ << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Arg[Type]);
+ }
+ };
+
+ // Parse 'modifier'
+ auto [Type1, Mod1, Loc1] = ConsumeModifier();
+ if (Type1 < NumberOfModifiers) {
+ SaveModifier(Type1, Mod1, Loc1);
+ if (Tok.is(tok::comma)) {
+ // Parse ',' 'modifier'
+ ConsumeAnyToken();
+ auto [Type2, Mod2, Loc2] = ConsumeModifier();
+ if (Type2 < NumberOfModifiers)
+ SaveModifier(Type2, Mod2, Loc2);
+ }
+ // Parse ':'
+ if (Tok.is(tok::colon))
+ ConsumeAnyToken();
+ else
+ Diag(Tok, diag::warn_pragma_expected_colon)
+ << "dyn_groupprivate modifier";
+ }
} else if (Kind == OMPC_num_tasks) {
// Parse optional <num_tasks modifier> ':'
OpenMPNumTasksClauseModifier Modifier =
@@ -4082,11 +4161,11 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
}
}
- bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
- (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
- Kind == OMPC_if || Kind == OMPC_device ||
- Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
- Kind == OMPC_num_threads;
+ bool NeedAnExpression =
+ (Kind == OMPC_schedule && DelimLoc.isValid()) ||
+ (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || Kind == OMPC_if ||
+ Kind == OMPC_device || Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
+ Kind == OMPC_num_threads || Kind == OMPC_dyn_groupprivate;
if (NeedAnExpression) {
SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(
@@ -4846,19 +4925,28 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
break;
Data.MotionModifiers.push_back(Modifier);
Data.MotionModifiersLoc.push_back(Tok.getLocation());
- ConsumeToken();
- if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
- IsInvalidMapperModifier = parseMapperModifier(Data);
- if (IsInvalidMapperModifier)
+ if (PP.getSpelling(Tok) == "iterator" && getLangOpts().OpenMP >= 51) {
+ ExprResult Tail;
+ Tail = ParseOpenMPIteratorsExpr();
+ Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
+ /*DiscardedValue=*/false);
+ if (Tail.isUsable())
+ Data.IteratorExpr = Tail.get();
+ } else {
+ ConsumeToken();
+ if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
+ IsInvalidMapperModifier = parseMapperModifier(Data);
+ if (IsInvalidMapperModifier)
+ break;
+ }
+ // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
+ if (getLangOpts().OpenMP < 51)
break;
+ // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
+ // TODO: Is that intentional?
+ if (Tok.is(tok::comma))
+ ConsumeToken();
}
- // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
- if (getLangOpts().OpenMP < 51)
- break;
- // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
- // TODO: Is that intentional?
- if (Tok.is(tok::comma))
- ConsumeToken();
}
if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
if (!IsInvalidMapperModifier) {
@@ -4931,6 +5019,37 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
ConsumeToken();
if (Tok.is(tok::colon))
Data.ColonLoc = Tok.getLocation();
+ if (getLangOpts().OpenMP >= 61) {
+ // Handle the optional fallback argument for the need_device_ptr
+ // modifier.
+ if (Tok.is(tok::l_paren)) {
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ T.consumeOpen();
+ if (Tok.is(tok::identifier)) {
+ std::string Modifier = PP.getSpelling(Tok);
+ if (Modifier == "fb_nullify" || Modifier == "fb_preserve") {
+ Data.NeedDevicePtrModifier =
+ Modifier == "fb_nullify" ? OMPC_NEED_DEVICE_PTR_fb_nullify
+ : OMPC_NEED_DEVICE_PTR_fb_preserve;
+ } else {
+ Diag(Tok, diag::err_omp_unknown_need_device_ptr_kind);
+ SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ return false;
+ }
+ ConsumeToken();
+ if (Tok.is(tok::r_paren)) {
+ Data.NeedDevicePtrModifierLoc = Tok.getLocation();
+ ConsumeAnyToken();
+ } else {
+ Diag(Tok, diag::err_expected) << tok::r_paren;
+ SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ return false;
+ }
+ }
+ }
+ }
ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
"adjust-op");
}
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 9203898..7e73d89c 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -813,7 +813,7 @@ StmtResult Parser::ParseCaseStatement(ParsedStmtContext StmtCtx,
return StmtError();
}
} else {
- LHS = Expr;
+ LHS = Actions.ActOnCaseExpr(CaseLoc, Expr);
MissingCase = false;
}
@@ -1079,16 +1079,10 @@ bool Parser::ConsumeNullStmt(StmtVector &Stmts) {
StmtResult Parser::handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx) {
bool IsStmtExprResult = false;
if ((StmtCtx & ParsedStmtContext::InStmtExpr) != ParsedStmtContext()) {
- // For GCC compatibility we skip past NullStmts.
- unsigned LookAhead = 0;
- while (GetLookAheadToken(LookAhead).is(tok::semi)) {
- ++LookAhead;
- }
- // Then look to see if the next two tokens close the statement expression;
- // if so, this expression statement is the last statement in a statement
- // expression.
- IsStmtExprResult = GetLookAheadToken(LookAhead).is(tok::r_brace) &&
- GetLookAheadToken(LookAhead + 1).is(tok::r_paren);
+ // Look ahead to see if the next two tokens close the statement expression;
+ // if so, this expression statement is the last statement in a
+ // statment expression.
+ IsStmtExprResult = Tok.is(tok::r_brace) && NextToken().is(tok::r_paren);
}
if (IsStmtExprResult)
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index 82f2294..9622a00 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1063,7 +1063,7 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,
return TPResult::False;
}
- if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) {
+ if (Next.isNoneOf(tok::coloncolon, tok::less, tok::colon)) {
// Determine whether this is a valid expression. If not, we will hit
// a parse error one way or another. In that case, tell the caller that
// this is ambiguous. Typo-correct to type and expression keywords and
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index a6fc676..7b425dd 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1100,30 +1100,25 @@ Parser::DeclGroupPtrTy Parser::ParseDeclOrFunctionDefInternal(
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
// declaration-specifiers init-declarator-list[opt] ';'
if (Tok.is(tok::semi)) {
- auto LengthOfTSTToken = [](DeclSpec::TST TKind) {
- assert(DeclSpec::isDeclRep(TKind));
- switch(TKind) {
- case DeclSpec::TST_class:
- return 5;
- case DeclSpec::TST_struct:
- return 6;
- case DeclSpec::TST_union:
- return 5;
- case DeclSpec::TST_enum:
- return 4;
- case DeclSpec::TST_interface:
- return 9;
- default:
- llvm_unreachable("we only expect to get the length of the class/struct/union/enum");
+ // Suggest correct location to fix '[[attrib]] struct' to 'struct
+ // [[attrib]]'
+ SourceLocation CorrectLocationForAttributes{};
+ TypeSpecifierType TKind = DS.getTypeSpecType();
+ if (DeclSpec::isDeclRep(TKind)) {
+ if (TKind == DeclSpec::TST_enum) {
+ if (const auto *ED = dyn_cast_or_null<EnumDecl>(DS.getRepAsDecl())) {
+ CorrectLocationForAttributes =
+ PP.getLocForEndOfToken(ED->getEnumKeyRange().getEnd());
+ }
}
-
- };
- // Suggest correct location to fix '[[attrib]] struct' to 'struct [[attrib]]'
- SourceLocation CorrectLocationForAttributes =
- DeclSpec::isDeclRep(DS.getTypeSpecType())
- ? DS.getTypeSpecTypeLoc().getLocWithOffset(
- LengthOfTSTToken(DS.getTypeSpecType()))
- : SourceLocation();
+ if (CorrectLocationForAttributes.isInvalid()) {
+ const auto &Policy = Actions.getASTContext().getPrintingPolicy();
+ unsigned Offset =
+ StringRef(DeclSpec::getSpecifierName(TKind, Policy)).size();
+ CorrectLocationForAttributes =
+ DS.getTypeSpecTypeLoc().getLocWithOffset(Offset);
+ }
+ }
ProhibitAttributes(Attrs, CorrectLocationForAttributes);
ConsumeToken();
RecordDecl *AnonRecord = nullptr;