From b4b3578af7d013f5fe4f4bb323bc52bc2991ae33 Mon Sep 17 00:00:00 2001 From: Serge Pavlov Date: Tue, 22 Jul 2014 01:54:49 +0000 Subject: [PATCH] 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 --- clang/include/clang/Sema/Sema.h | 2 +- clang/lib/Parse/ParseCXXInlineMethods.cpp | 3 ++- clang/lib/Parse/ParseDecl.cpp | 4 ++-- clang/lib/Sema/SemaDeclCXX.cpp | 5 ++++- clang/test/SemaCXX/default1.cpp | 3 +++ 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 83488d0..8dba089 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -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); diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 310e2b4..30a9120 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -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 diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 74df162..62d4376 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -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 diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index a0534ff..c5cd83d 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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(param); Param->setInvalidDecl(); UnparsedDefaultArgLocs.erase(Param); + Param->setDefaultArg(new(Context) + OpaqueValueExpr(EqualLoc, Param->getType(), VK_RValue)); } /// CheckExtraCXXDefaultArguments - Check for any extra default diff --git a/clang/test/SemaCXX/default1.cpp b/clang/test/SemaCXX/default1.cpp index b661776..23466fa 100644 --- a/clang/test/SemaCXX/default1.cpp +++ b/clang/test/SemaCXX/default1.cpp @@ -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); -- 2.7.4