brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.6 KiB · 0e86c4c Raw
607 lines · cpp
1//===--- ParseInit.cpp - Initializer Parsing ------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements initializer parsing as specified by C99 6.7.8.10//11//===----------------------------------------------------------------------===//12 13#include "clang/Basic/DiagnosticParse.h"14#include "clang/Basic/TokenKinds.h"15#include "clang/Parse/Parser.h"16#include "clang/Parse/RAIIObjectsForParser.h"17#include "clang/Sema/Designator.h"18#include "clang/Sema/EnterExpressionEvaluationContext.h"19#include "clang/Sema/Ownership.h"20#include "clang/Sema/Scope.h"21#include "clang/Sema/SemaCodeCompletion.h"22#include "clang/Sema/SemaObjC.h"23using namespace clang;24 25bool Parser::MayBeDesignationStart() {26  switch (Tok.getKind()) {27  default:28    return false;29 30  case tok::period:      // designator: '.' identifier31    return true;32 33  case tok::l_square: {  // designator: array-designator34    if (!PP.getLangOpts().CPlusPlus)35      return true;36 37    // C++11 lambda expressions and C99 designators can be ambiguous all the38    // way through the closing ']' and to the next character. Handle the easy39    // cases here, and fall back to tentative parsing if those fail.40    switch (PP.LookAhead(0).getKind()) {41    case tok::equal:42    case tok::ellipsis:43    case tok::r_square:44      // Definitely starts a lambda expression.45      return false;46 47    case tok::amp:48    case tok::kw_this:49    case tok::star:50    case tok::identifier:51      // We have to do additional analysis, because these could be the52      // start of a constant expression or a lambda capture list.53      break;54 55    default:56      // Anything not mentioned above cannot occur following a '[' in a57      // lambda expression.58      return true;59    }60 61    // Handle the complicated case below.62    break;63  }64  case tok::identifier:  // designation: identifier ':'65    return PP.LookAhead(0).is(tok::colon);66  }67 68  // Parse up to (at most) the token after the closing ']' to determine69  // whether this is a C99 designator or a lambda.70  RevertingTentativeParsingAction Tentative(*this);71 72  LambdaIntroducer Intro;73  LambdaIntroducerTentativeParse ParseResult;74  if (ParseLambdaIntroducer(Intro, &ParseResult)) {75    // Hit and diagnosed an error in a lambda.76    // FIXME: Tell the caller this happened so they can recover.77    return true;78  }79 80  switch (ParseResult) {81  case LambdaIntroducerTentativeParse::Success:82  case LambdaIntroducerTentativeParse::Incomplete:83    // Might be a lambda-expression. Keep looking.84    // FIXME: If our tentative parse was not incomplete, parse the lambda from85    // here rather than throwing away then reparsing the LambdaIntroducer.86    break;87 88  case LambdaIntroducerTentativeParse::MessageSend:89  case LambdaIntroducerTentativeParse::Invalid:90    // Can't be a lambda-expression. Treat it as a designator.91    // FIXME: Should we disambiguate against a message-send?92    return true;93  }94 95  // Once we hit the closing square bracket, we look at the next96  // token. If it's an '=', this is a designator. Otherwise, it's a97  // lambda expression. This decision favors lambdas over the older98  // GNU designator syntax, which allows one to omit the '=', but is99  // consistent with GCC.100  return Tok.is(tok::equal);101}102 103static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc,104                                       Designation &Desig) {105  // If we have exactly one array designator, this used the GNU106  // 'designation: array-designator' extension, otherwise there should be no107  // designators at all!108  if (Desig.getNumDesignators() == 1 &&109      (Desig.getDesignator(0).isArrayDesignator() ||110       Desig.getDesignator(0).isArrayRangeDesignator()))111    P.Diag(Loc, diag::ext_gnu_missing_equal_designator);112  else if (Desig.getNumDesignators() > 0)113    P.Diag(Loc, diag::err_expected_equal_designator);114}115 116ExprResult Parser::ParseInitializerWithPotentialDesignator(117    DesignatorCompletionInfo DesignatorCompletion) {118  // If this is the old-style GNU extension:119  //   designation ::= identifier ':'120  // Handle it as a field designator.  Otherwise, this must be the start of a121  // normal expression.122  if (Tok.is(tok::identifier)) {123    const IdentifierInfo *FieldName = Tok.getIdentifierInfo();124 125    SmallString<256> NewSyntax;126    llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName()127                                         << " = ";128 129    SourceLocation NameLoc = ConsumeToken(); // Eat the identifier.130 131    assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!");132    SourceLocation ColonLoc = ConsumeToken();133 134    Diag(NameLoc, diag::ext_gnu_old_style_field_designator)135      << FixItHint::CreateReplacement(SourceRange(NameLoc, ColonLoc),136                                      NewSyntax);137 138    Designation D;139    D.AddDesignator(Designator::CreateFieldDesignator(140        FieldName, SourceLocation(), NameLoc));141    PreferredType.enterDesignatedInitializer(142        Tok.getLocation(), DesignatorCompletion.PreferredBaseType, D);143    return Actions.ActOnDesignatedInitializer(D, ColonLoc, true,144                                              ParseInitializer());145  }146 147  // Desig - This is initialized when we see our first designator.  We may have148  // an objc message send with no designator, so we don't want to create this149  // eagerly.150  Designation Desig;151 152  // Parse each designator in the designator list until we find an initializer.153  while (Tok.is(tok::period) || Tok.is(tok::l_square)) {154    if (Tok.is(tok::period)) {155      // designator: '.' identifier156      SourceLocation DotLoc = ConsumeToken();157 158      if (Tok.is(tok::code_completion)) {159        cutOffParsing();160        Actions.CodeCompletion().CodeCompleteDesignator(161            DesignatorCompletion.PreferredBaseType,162            DesignatorCompletion.InitExprs, Desig);163        return ExprError();164      }165      if (Tok.isNot(tok::identifier)) {166        Diag(Tok.getLocation(), diag::err_expected_field_designator);167        return ExprError();168      }169 170      Desig.AddDesignator(Designator::CreateFieldDesignator(171          Tok.getIdentifierInfo(), DotLoc, Tok.getLocation()));172      ConsumeToken(); // Eat the identifier.173      continue;174    }175 176    // We must have either an array designator now or an objc message send.177    assert(Tok.is(tok::l_square) && "Unexpected token!");178 179    // Handle the two forms of array designator:180    //   array-designator: '[' constant-expression ']'181    //   array-designator: '[' constant-expression '...' constant-expression ']'182    //183    // Also, we have to handle the case where the expression after the184    // designator an an objc message send: '[' objc-message-expr ']'.185    // Interesting cases are:186    //   [foo bar]         -> objc message send187    //   [foo]             -> array designator188    //   [foo ... bar]     -> array designator189    //   [4][foo bar]      -> obsolete GNU designation with objc message send.190    //191    // We do not need to check for an expression starting with [[ here. If it192    // contains an Objective-C message send, then it is not an ill-formed193    // attribute. If it is a lambda-expression within an array-designator, then194    // it will be rejected because a constant-expression cannot begin with a195    // lambda-expression.196    InMessageExpressionRAIIObject InMessage(*this, true);197 198    BalancedDelimiterTracker T(*this, tok::l_square);199    T.consumeOpen();200    SourceLocation StartLoc = T.getOpenLocation();201 202    ExprResult Idx;203 204    // If Objective-C is enabled and this is a typename (class message205    // send) or send to 'super', parse this as a message send206    // expression.  We handle C++ and C separately, since C++ requires207    // much more complicated parsing.208    if  (getLangOpts().ObjC && getLangOpts().CPlusPlus) {209      // Send to 'super'.210      if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&211          NextToken().isNot(tok::period) &&212          getCurScope()->isInObjcMethodScope()) {213        CheckArrayDesignatorSyntax(*this, StartLoc, Desig);214        return ParseAssignmentExprWithObjCMessageExprStart(215            StartLoc, ConsumeToken(), nullptr, nullptr);216      }217 218      // Parse the receiver, which is either a type or an expression.219      bool IsExpr;220      void *TypeOrExpr;221      if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {222        SkipUntil(tok::r_square, StopAtSemi);223        return ExprError();224      }225 226      // If the receiver was a type, we have a class message; parse227      // the rest of it.228      if (!IsExpr) {229        CheckArrayDesignatorSyntax(*this, StartLoc, Desig);230        return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,231                                                           SourceLocation(),232                                   ParsedType::getFromOpaquePtr(TypeOrExpr),233                                                           nullptr);234      }235 236      // If the receiver was an expression, we still don't know237      // whether we have a message send or an array designator; just238      // adopt the expression for further analysis below.239      // FIXME: potentially-potentially evaluated expression above?240      Idx = ExprResult(static_cast<Expr*>(TypeOrExpr));241    } else if (getLangOpts().ObjC && Tok.is(tok::identifier)) {242      IdentifierInfo *II = Tok.getIdentifierInfo();243      SourceLocation IILoc = Tok.getLocation();244      ParsedType ReceiverType;245      // Three cases. This is a message send to a type: [type foo]246      // This is a message send to super:  [super foo]247      // This is a message sent to an expr:  [super.bar foo]248      switch (Actions.ObjC().getObjCMessageKind(249          getCurScope(), II, IILoc, II == Ident_super,250          NextToken().is(tok::period), ReceiverType)) {251      case SemaObjC::ObjCSuperMessage:252        CheckArrayDesignatorSyntax(*this, StartLoc, Desig);253        return ParseAssignmentExprWithObjCMessageExprStart(254            StartLoc, ConsumeToken(), nullptr, nullptr);255 256      case SemaObjC::ObjCClassMessage:257        CheckArrayDesignatorSyntax(*this, StartLoc, Desig);258        ConsumeToken(); // the identifier259        if (!ReceiverType) {260          SkipUntil(tok::r_square, StopAtSemi);261          return ExprError();262        }263 264        // Parse type arguments and protocol qualifiers.265        if (Tok.is(tok::less)) {266          SourceLocation NewEndLoc;267          TypeResult NewReceiverType268            = parseObjCTypeArgsAndProtocolQualifiers(IILoc, ReceiverType,269                                                     /*consumeLastToken=*/true,270                                                     NewEndLoc);271          if (!NewReceiverType.isUsable()) {272            SkipUntil(tok::r_square, StopAtSemi);273            return ExprError();274          }275 276          ReceiverType = NewReceiverType.get();277        }278 279        return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,280                                                           SourceLocation(),281                                                           ReceiverType,282                                                           nullptr);283 284      case SemaObjC::ObjCInstanceMessage:285        // Fall through; we'll just parse the expression and286        // (possibly) treat this like an Objective-C message send287        // later.288        break;289      }290    }291 292    // Parse the index expression, if we haven't already gotten one293    // above (which can only happen in Objective-C++).294    // Note that we parse this as an assignment expression, not a constant295    // expression (allowing *=, =, etc) to handle the objc case.  Sema needs296    // to validate that the expression is a constant.297    // FIXME: We also need to tell Sema that we're in a298    // potentially-potentially evaluated context.299    if (!Idx.get()) {300      Idx = ParseAssignmentExpression();301      if (Idx.isInvalid()) {302        SkipUntil(tok::r_square, StopAtSemi);303        return Idx;304      }305    }306 307    // Given an expression, we could either have a designator (if the next308    // tokens are '...' or ']' or an objc message send.  If this is an objc309    // message send, handle it now.  An objc-message send is the start of310    // an assignment-expression production.311    if (getLangOpts().ObjC && Tok.isNot(tok::ellipsis) &&312        Tok.isNot(tok::r_square)) {313      CheckArrayDesignatorSyntax(*this, Tok.getLocation(), Desig);314      return ParseAssignmentExprWithObjCMessageExprStart(315          StartLoc, SourceLocation(), nullptr, Idx.get());316    }317 318    // If this is a normal array designator, remember it.319    if (Tok.isNot(tok::ellipsis)) {320      Desig.AddDesignator(Designator::CreateArrayDesignator(Idx.get(),321                                                            StartLoc));322    } else {323      // Handle the gnu array range extension.324      Diag(Tok, diag::ext_gnu_array_range);325      SourceLocation EllipsisLoc = ConsumeToken();326 327      ExprResult RHS(ParseConstantExpression());328      if (RHS.isInvalid()) {329        SkipUntil(tok::r_square, StopAtSemi);330        return RHS;331      }332      Desig.AddDesignator(Designator::CreateArrayRangeDesignator(333          Idx.get(), RHS.get(), StartLoc, EllipsisLoc));334    }335 336    T.consumeClose();337    Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc(338                                                        T.getCloseLocation());339  }340 341  // Okay, we're done with the designator sequence.  We know that there must be342  // at least one designator, because the only case we can get into this method343  // without a designator is when we have an objc message send.  That case is344  // handled and returned from above.345  assert(!Desig.empty() && "Designator is empty?");346 347  // Handle a normal designator sequence end, which is an equal.348  if (Tok.is(tok::equal)) {349    SourceLocation EqualLoc = ConsumeToken();350    PreferredType.enterDesignatedInitializer(351        Tok.getLocation(), DesignatorCompletion.PreferredBaseType, Desig);352    return Actions.ActOnDesignatedInitializer(Desig, EqualLoc, false,353                                              ParseInitializer());354  }355 356  // Handle a C++20 braced designated initialization, which results in357  // direct-list-initialization of the aggregate element. We allow this as an358  // extension from C++11 onwards (when direct-list-initialization was added).359  if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus11) {360    PreferredType.enterDesignatedInitializer(361        Tok.getLocation(), DesignatorCompletion.PreferredBaseType, Desig);362    return Actions.ActOnDesignatedInitializer(Desig, SourceLocation(), false,363                                              ParseBraceInitializer());364  }365 366  // We read some number of designators and found something that isn't an = or367  // an initializer.  If we have exactly one array designator, this368  // is the GNU 'designation: array-designator' extension.  Otherwise, it is a369  // parse error.370  if (Desig.getNumDesignators() == 1 &&371      (Desig.getDesignator(0).isArrayDesignator() ||372       Desig.getDesignator(0).isArrayRangeDesignator())) {373    Diag(Tok, diag::ext_gnu_missing_equal_designator)374      << FixItHint::CreateInsertion(Tok.getLocation(), "= ");375    return Actions.ActOnDesignatedInitializer(Desig, Tok.getLocation(),376                                              true, ParseInitializer());377  }378 379  Diag(Tok, diag::err_expected_equal_designator);380  return ExprError();381}382 383ExprResult Parser::createEmbedExpr() {384  assert(Tok.getKind() == tok::annot_embed);385  EmbedAnnotationData *Data =386      reinterpret_cast<EmbedAnnotationData *>(Tok.getAnnotationValue());387  ExprResult Res;388  ASTContext &Context = Actions.getASTContext();389  SourceLocation StartLoc = ConsumeAnnotationToken();390  if (Data->BinaryData.size() == 1) {391    Res = IntegerLiteral::Create(392        Context, llvm::APInt(CHAR_BIT, (unsigned char)Data->BinaryData.back()),393        Context.UnsignedCharTy, StartLoc);394  } else {395    auto CreateStringLiteralFromStringRef = [&](StringRef Str, QualType Ty) {396      llvm::APSInt ArraySize =397          Context.MakeIntValue(Str.size(), Context.getSizeType());398      QualType ArrayTy = Context.getConstantArrayType(399          Ty, ArraySize, nullptr, ArraySizeModifier::Normal, 0);400      return StringLiteral::Create(Context, Str, StringLiteralKind::Binary,401                                   false, ArrayTy, StartLoc);402    };403 404    StringLiteral *BinaryDataArg = CreateStringLiteralFromStringRef(405        Data->BinaryData, Context.UnsignedCharTy);406    Res = Actions.ActOnEmbedExpr(StartLoc, BinaryDataArg, Data->FileName);407  }408  return Res;409}410 411ExprResult Parser::ParseBraceInitializer() {412  InMessageExpressionRAIIObject InMessage(*this, false);413 414  BalancedDelimiterTracker T(*this, tok::l_brace);415  T.consumeOpen();416  SourceLocation LBraceLoc = T.getOpenLocation();417 418  /// InitExprs - This is the actual list of expressions contained in the419  /// initializer.420  ExprVector InitExprs;421 422  if (Tok.is(tok::r_brace)) {423    // Empty initializers are a C++ feature and a GNU extension to C before C23.424    if (!getLangOpts().CPlusPlus) {425      Diag(LBraceLoc, getLangOpts().C23426                          ? diag::warn_c23_compat_empty_initializer427                          : diag::ext_c_empty_initializer);428    }429    // Match the '}'.430    return Actions.ActOnInitList(LBraceLoc, {}, ConsumeBrace());431  }432 433  // Enter an appropriate expression evaluation context for an initializer list.434  EnterExpressionEvaluationContext EnterContext(435      Actions, EnterExpressionEvaluationContext::InitList);436 437  bool InitExprsOk = true;438  QualType LikelyType = PreferredType.get(T.getOpenLocation());439  DesignatorCompletionInfo DesignatorCompletion{InitExprs, LikelyType};440  bool CalledSignatureHelp = false;441  auto RunSignatureHelp = [&] {442    QualType PreferredType;443    if (!LikelyType.isNull())444      PreferredType = Actions.CodeCompletion().ProduceConstructorSignatureHelp(445          LikelyType->getCanonicalTypeInternal(), T.getOpenLocation(),446          InitExprs, T.getOpenLocation(), /*Braced=*/true);447    CalledSignatureHelp = true;448    return PreferredType;449  };450 451  while (true) {452    PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);453 454    // Handle Microsoft __if_exists/if_not_exists if necessary.455    if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||456        Tok.is(tok::kw___if_not_exists))) {457      if (ParseMicrosoftIfExistsBraceInitializer(InitExprs, InitExprsOk)) {458        if (Tok.isNot(tok::comma)) break;459        ConsumeToken();460      }461      if (Tok.is(tok::r_brace)) break;462      continue;463    }464 465    // Parse: designation[opt] initializer466 467    // If we know that this cannot be a designation, just parse the nested468    // initializer directly.469    ExprResult SubElt;470    if (MayBeDesignationStart())471      SubElt = ParseInitializerWithPotentialDesignator(DesignatorCompletion);472    else if (Tok.getKind() == tok::annot_embed)473      SubElt = createEmbedExpr();474    else475      SubElt = ParseInitializer();476 477    if (Tok.is(tok::ellipsis))478      SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken());479 480    // If we couldn't parse the subelement, bail out.481    if (SubElt.isUsable()) {482      InitExprs.push_back(SubElt.get());483    } else {484      InitExprsOk = false;485 486      // We have two ways to try to recover from this error: if the code looks487      // grammatically ok (i.e. we have a comma coming up) try to continue488      // parsing the rest of the initializer.  This allows us to emit489      // diagnostics for later elements that we find.  If we don't see a comma,490      // assume there is a parse error, and just skip to recover.491      // FIXME: This comment doesn't sound right. If there is a r_brace492      // immediately, it can't be an error, since there is no other way of493      // leaving this loop except through this if.494      if (Tok.isNot(tok::comma)) {495        SkipUntil(tok::r_brace, StopBeforeMatch);496        break;497      }498    }499 500    // If we don't have a comma continued list, we're done.501    if (Tok.isNot(tok::comma)) break;502 503    // TODO: save comma locations if some client cares.504    ConsumeToken();505 506    // Handle trailing comma.507    if (Tok.is(tok::r_brace)) break;508  }509 510  bool closed = !T.consumeClose();511 512  if (InitExprsOk && closed)513    return Actions.ActOnInitList(LBraceLoc, InitExprs,514                                 T.getCloseLocation());515 516  return ExprError(); // an error occurred.517}518 519bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,520                                                    bool &InitExprsOk) {521  bool trailingComma = false;522  IfExistsCondition Result;523  if (ParseMicrosoftIfExistsCondition(Result))524    return false;525 526  BalancedDelimiterTracker Braces(*this, tok::l_brace);527  if (Braces.consumeOpen()) {528    Diag(Tok, diag::err_expected) << tok::l_brace;529    return false;530  }531 532  switch (Result.Behavior) {533  case IfExistsBehavior::Parse:534    // Parse the declarations below.535    break;536 537  case IfExistsBehavior::Dependent:538    Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists)539      << Result.IsIfExists;540    // Fall through to skip.541    [[fallthrough]];542 543  case IfExistsBehavior::Skip:544    Braces.skipToEnd();545    return false;546  }547 548  DesignatorCompletionInfo DesignatorCompletion{549      InitExprs,550      PreferredType.get(Braces.getOpenLocation()),551  };552  while (!isEofOrEom()) {553    trailingComma = false;554    // If we know that this cannot be a designation, just parse the nested555    // initializer directly.556    ExprResult SubElt;557    if (MayBeDesignationStart())558      SubElt = ParseInitializerWithPotentialDesignator(DesignatorCompletion);559    else560      SubElt = ParseInitializer();561 562    if (Tok.is(tok::ellipsis))563      SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken());564 565    // If we couldn't parse the subelement, bail out.566    if (!SubElt.isInvalid())567      InitExprs.push_back(SubElt.get());568    else569      InitExprsOk = false;570 571    if (Tok.is(tok::comma)) {572      ConsumeToken();573      trailingComma = true;574    }575 576    if (Tok.is(tok::r_brace))577      break;578  }579 580  Braces.consumeClose();581 582  return !trailingComma;583}584 585ExprResult Parser::ParseInitializer(Decl *DeclForInitializer) {586  // Set DeclForInitializer for file-scope variables.587  // For constexpr references, set it to suppress runtime warnings.588  // For non-constexpr references, don't set it to avoid evaluation issues589  // with self-referencing initializers. Local variables (including local590  // constexpr) should emit runtime warnings.591  if (DeclForInitializer && !Actions.ExprEvalContexts.empty()) {592    if (auto *VD = dyn_cast<VarDecl>(DeclForInitializer);593        VD && VD->isFileVarDecl() &&594        (!VD->getType()->isReferenceType() || VD->isConstexpr()))595      Actions.ExprEvalContexts.back().DeclForInitializer = VD;596  }597 598  ExprResult init;599  if (Tok.isNot(tok::l_brace)) {600    init = ParseAssignmentExpression();601  } else {602    init = ParseBraceInitializer();603  }604 605  return init;606}607