forked from OSchip/llvm-project
Add missing direct-init / parameter-declaration-clause disambiguation when
parsing a trailing-return-type of a (function pointer) variable declaration. llvm-svn: 324151
This commit is contained in:
parent
6a8e79b8e5
commit
e303e3523a
|
@ -1644,7 +1644,8 @@ private:
|
|||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++0x 8: Function declaration trailing-return-type
|
||||
TypeResult ParseTrailingReturnType(SourceRange &Range);
|
||||
TypeResult ParseTrailingReturnType(SourceRange &Range,
|
||||
bool MayBeFollowedByDirectInit);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ 2.13.5: C++ Boolean Literals
|
||||
|
@ -2158,7 +2159,8 @@ private:
|
|||
TPResult TryParsePtrOperatorSeq();
|
||||
TPResult TryParseOperatorId();
|
||||
TPResult TryParseInitDeclaratorList();
|
||||
TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true);
|
||||
TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier = true,
|
||||
bool mayHaveDirectInit = false);
|
||||
TPResult
|
||||
TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = nullptr,
|
||||
bool VersusTemplateArg = false);
|
||||
|
|
|
@ -1731,6 +1731,7 @@ enum class DeclaratorContext {
|
|||
LambdaExprParameterContext, // Lambda-expression parameter declarator.
|
||||
ConversionIdContext, // C++ conversion-type-id.
|
||||
TrailingReturnContext, // C++11 trailing-type-specifier.
|
||||
TrailingReturnVarContext, // C++11 trailing-type-specifier for variable.
|
||||
TemplateTypeArgContext, // Template type argument.
|
||||
AliasDeclContext, // C++11 alias-declaration.
|
||||
AliasTemplateContext // C++11 alias-declaration template.
|
||||
|
@ -1950,6 +1951,7 @@ public:
|
|||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
case DeclaratorContext::TrailingReturnVarContext:
|
||||
return true;
|
||||
}
|
||||
llvm_unreachable("unknown context kind!");
|
||||
|
@ -1986,6 +1988,7 @@ public:
|
|||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
case DeclaratorContext::TrailingReturnVarContext:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("unknown context kind!");
|
||||
|
@ -2026,6 +2029,7 @@ public:
|
|||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
case DeclaratorContext::TrailingReturnVarContext:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("unknown context kind!");
|
||||
|
@ -2052,6 +2056,7 @@ public:
|
|||
case DeclaratorContext::BlockContext:
|
||||
case DeclaratorContext::ForContext:
|
||||
case DeclaratorContext::InitStmtContext:
|
||||
case DeclaratorContext::TrailingReturnVarContext:
|
||||
return true;
|
||||
|
||||
case DeclaratorContext::ConditionContext:
|
||||
|
@ -2288,6 +2293,7 @@ public:
|
|||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
case DeclaratorContext::TrailingReturnVarContext:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("unknown context kind!");
|
||||
|
@ -2319,6 +2325,7 @@ public:
|
|||
case DeclaratorContext::LambdaExprContext:
|
||||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
case DeclaratorContext::TrailingReturnVarContext:
|
||||
return false;
|
||||
|
||||
case DeclaratorContext::BlockContext:
|
||||
|
|
|
@ -2671,7 +2671,8 @@ Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) {
|
|||
return DeclSpecContext::DSC_template_param;
|
||||
if (Context == DeclaratorContext::TemplateTypeArgContext)
|
||||
return DeclSpecContext::DSC_template_type_arg;
|
||||
if (Context == DeclaratorContext::TrailingReturnContext)
|
||||
if (Context == DeclaratorContext::TrailingReturnContext ||
|
||||
Context == DeclaratorContext::TrailingReturnVarContext)
|
||||
return DeclSpecContext::DSC_trailing;
|
||||
if (Context == DeclaratorContext::AliasDeclContext ||
|
||||
Context == DeclaratorContext::AliasTemplateContext)
|
||||
|
@ -5627,7 +5628,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
|||
D.getContext() == DeclaratorContext::AliasTemplateContext)
|
||||
// The most likely error is that the ';' was forgotten.
|
||||
DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi);
|
||||
else if (D.getContext() == DeclaratorContext::TrailingReturnContext &&
|
||||
else if ((D.getContext() == DeclaratorContext::TrailingReturnContext ||
|
||||
D.getContext() == DeclaratorContext::TrailingReturnVarContext) &&
|
||||
!isCXX11VirtSpecifier(Tok))
|
||||
DiagnoseIdentifier = NextToken().isOneOf(
|
||||
tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try);
|
||||
|
@ -5641,6 +5643,18 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
|||
}
|
||||
|
||||
if (Tok.is(tok::l_paren)) {
|
||||
// If this might be an abstract-declarator followed by a direct-initializer,
|
||||
// check whether this is a valid declarator chunk. If it can't be, assume
|
||||
// that it's an initializer instead.
|
||||
if (D.mayOmitIdentifier() && D.mayBeFollowedByCXXDirectInit()) {
|
||||
RevertingTentativeParsingAction PA(*this);
|
||||
if (TryParseDeclarator(true, D.mayHaveIdentifier(), true) ==
|
||||
TPResult::False) {
|
||||
D.SetIdentifier(nullptr, Tok.getLocation());
|
||||
goto PastIdentifier;
|
||||
}
|
||||
}
|
||||
|
||||
// direct-declarator: '(' declarator ')'
|
||||
// direct-declarator: '(' attributes declarator ')'
|
||||
// Example: 'char (*X)' or 'int (*XX)(void)'
|
||||
|
@ -6111,7 +6125,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
|
|||
StartLoc = D.getDeclSpec().getTypeSpecTypeLoc();
|
||||
LocalEndLoc = Tok.getLocation();
|
||||
SourceRange Range;
|
||||
TrailingReturnType = ParseTrailingReturnType(Range);
|
||||
TrailingReturnType =
|
||||
ParseTrailingReturnType(Range, D.mayBeFollowedByCXXDirectInit());
|
||||
EndLoc = Range.getEnd();
|
||||
}
|
||||
} else if (standardAttributesAllowed()) {
|
||||
|
|
|
@ -3706,12 +3706,15 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
|
|||
|
||||
/// ParseTrailingReturnType - Parse a trailing return type on a new-style
|
||||
/// function declaration.
|
||||
TypeResult Parser::ParseTrailingReturnType(SourceRange &Range) {
|
||||
TypeResult Parser::ParseTrailingReturnType(SourceRange &Range,
|
||||
bool MayBeFollowedByDirectInit) {
|
||||
assert(Tok.is(tok::arrow) && "expected arrow");
|
||||
|
||||
ConsumeToken();
|
||||
|
||||
return ParseTypeName(&Range, DeclaratorContext::TrailingReturnContext);
|
||||
return ParseTypeName(&Range, MayBeFollowedByDirectInit
|
||||
? DeclaratorContext::TrailingReturnVarContext
|
||||
: DeclaratorContext::TrailingReturnContext);
|
||||
}
|
||||
|
||||
/// \brief We have just started parsing the definition of a new class,
|
||||
|
|
|
@ -1183,7 +1183,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
|||
if (Tok.is(tok::arrow)) {
|
||||
FunLocalRangeEnd = Tok.getLocation();
|
||||
SourceRange Range;
|
||||
TrailingReturnType = ParseTrailingReturnType(Range);
|
||||
TrailingReturnType =
|
||||
ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit*/ false);
|
||||
if (Range.getEnd().isValid())
|
||||
DeclEndLoc = Range.getEnd();
|
||||
}
|
||||
|
@ -1253,7 +1254,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
|||
// Parse the return type, if there is one.
|
||||
if (Tok.is(tok::arrow)) {
|
||||
SourceRange Range;
|
||||
TrailingReturnType = ParseTrailingReturnType(Range);
|
||||
TrailingReturnType =
|
||||
ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit*/ false);
|
||||
if (Range.getEnd().isValid())
|
||||
DeclEndLoc = Range.getEnd();
|
||||
}
|
||||
|
|
|
@ -873,7 +873,8 @@ Parser::TPResult Parser::TryParseOperatorId() {
|
|||
/// template-id [TODO]
|
||||
///
|
||||
Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
|
||||
bool mayHaveIdentifier) {
|
||||
bool mayHaveIdentifier,
|
||||
bool mayHaveDirectInit) {
|
||||
// declarator:
|
||||
// direct-declarator
|
||||
// ptr-operator declarator
|
||||
|
@ -930,6 +931,9 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
|
|||
return TPResult::False;
|
||||
}
|
||||
|
||||
if (mayHaveDirectInit)
|
||||
return TPResult::Ambiguous;
|
||||
|
||||
while (1) {
|
||||
TPResult TPR(TPResult::Ambiguous);
|
||||
|
||||
|
|
|
@ -2859,6 +2859,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
|||
Error = 12; // Type alias
|
||||
break;
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
case DeclaratorContext::TrailingReturnVarContext:
|
||||
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
|
||||
Error = 13; // Function return type
|
||||
break;
|
||||
|
@ -2961,6 +2962,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
|||
unsigned DiagID = 0;
|
||||
switch (D.getContext()) {
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
case DeclaratorContext::TrailingReturnVarContext:
|
||||
// Class and enumeration definitions are syntactically not allowed in
|
||||
// trailing return types.
|
||||
llvm_unreachable("parser should not have allowed this");
|
||||
|
@ -3914,6 +3916,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
case DeclaratorContext::ObjCResultContext:
|
||||
case DeclaratorContext::PrototypeContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
case DeclaratorContext::TrailingReturnVarContext:
|
||||
isFunctionOrMethod = true;
|
||||
LLVM_FALLTHROUGH;
|
||||
|
||||
|
@ -4954,6 +4957,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
case DeclaratorContext::LambdaExprContext:
|
||||
case DeclaratorContext::ConversionIdContext:
|
||||
case DeclaratorContext::TrailingReturnContext:
|
||||
case DeclaratorContext::TrailingReturnVarContext:
|
||||
case DeclaratorContext::TemplateTypeArgContext:
|
||||
// FIXME: We may want to allow parameter packs in block-literal contexts
|
||||
// in the future.
|
||||
|
|
|
@ -11,3 +11,7 @@ void f() {
|
|||
unknown *p = 0; // expected-error {{unknown type name 'unknown'}}
|
||||
unknown * p + 0; // expected-error {{undeclared identifier 'unknown'}}
|
||||
}
|
||||
|
||||
auto (*p)() -> int(nullptr);
|
||||
auto (*q)() -> int(*)(unknown); // expected-error {{unknown type name 'unknown'}}
|
||||
auto (*r)() -> int(*)(unknown + 1); // expected-error {{undeclared identifier 'unknown'}}
|
||||
|
|
|
@ -79,7 +79,7 @@ enum E
|
|||
namespace PR5066 {
|
||||
using T = int (*f)(); // expected-error {{type-id cannot have a name}}
|
||||
template<typename T> using U = int (*f)(); // expected-error {{type-id cannot have a name}}
|
||||
auto f() -> int (*f)(); // expected-error {{type-id cannot have a name}}
|
||||
auto f() -> int (*f)(); // expected-error {{only variables can be initialized}} expected-error {{expected ';'}}
|
||||
auto g = []() -> int (*f)() {}; // expected-error {{type-id cannot have a name}}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue