Commit b4b3578a authored by Serge Pavlov's avatar Serge Pavlov
Browse files

Avoid crash if default argument parsed with errors.

If function parameters have default values, and that of the second
parameter is parsed with errors, function declaration would have
a parameter without default value that follows a parameter with
that. Such declaration breaks logic of selecting overloaded
function. As a solution, put opaque object as default value in such case.

This patch fixes PR20055.

Differential Revision: http://reviews.llvm.org/D4378

llvm-svn: 213594
parent 1a711b16
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1625,7 +1625,7 @@ public:
  void ActOnParamUnparsedDefaultArgument(Decl *param,
                                         SourceLocation EqualLoc,
                                         SourceLocation ArgLoc);
  void ActOnParamDefaultArgumentError(Decl *param);
  void ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc);
  bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
                               SourceLocation EqualLoc);

+2 −1
Original line number Diff line number Diff line
@@ -337,7 +337,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
      } else
        DefArgResult = ParseAssignmentExpression();
      if (DefArgResult.isInvalid())
        Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
        Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param,
                                               EqualLoc);
      else {
        if (!TryConsumeToken(tok::cxx_defaultarg_end)) {
          // The last two tokens are the terminator and the saved value of
+2 −2
Original line number Diff line number Diff line
@@ -5436,7 +5436,7 @@ void Parser::ParseParameterDeclarationClause(
          if (!ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument)) {
            delete DefArgToks;
            DefArgToks = nullptr;
            Actions.ActOnParamDefaultArgumentError(Param);
            Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
          } else {
            // Mark the end of the default argument so that we know when to
            // stop when we parse it later on.
@@ -5465,7 +5465,7 @@ void Parser::ParseParameterDeclarationClause(
          } else
            DefArgResult = ParseAssignmentExpression();
          if (DefArgResult.isInvalid()) {
            Actions.ActOnParamDefaultArgumentError(Param);
            Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
            SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);
          } else {
            // Inform the actions module about the default argument
+4 −1
Original line number Diff line number Diff line
@@ -344,13 +344,16 @@ void Sema::ActOnParamUnparsedDefaultArgument(Decl *param,

/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
/// the default argument for the parameter param failed.
void Sema::ActOnParamDefaultArgumentError(Decl *param) {
void Sema::ActOnParamDefaultArgumentError(Decl *param,
                                          SourceLocation EqualLoc) {
  if (!param)
    return;

  ParmVarDecl *Param = cast<ParmVarDecl>(param);
  Param->setInvalidDecl();
  UnparsedDefaultArgLocs.erase(Param);
  Param->setDefaultArg(new(Context)
                       OpaqueValueExpr(EqualLoc, Param->getType(), VK_RValue));
}

/// CheckExtraCXXDefaultArguments - Check for any extra default
+3 −0
Original line number Diff line number Diff line
@@ -62,3 +62,6 @@ int i2() {
    j(2, 3); // expected-error{{too many arguments to function call, expected at most single argument 'f', have 2}}
  }
}

int pr20055_f(int x = 0, int y = UNDEFINED); // expected-error{{use of undeclared identifier}}
int pr20055_v = pr20055_f(0);