diff options
Diffstat (limited to 'clang/lib/Parse')
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 22 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseInit.cpp | 23 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 155 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseTentative.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Parse/Parser.cpp | 41 |
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; |
