summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Parse/Parser.h6
-rw-r--r--clang/include/clang/Sema/DeclSpec.h7
-rw-r--r--clang/lib/Parse/ParseDecl.cpp21
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp7
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp6
-rw-r--r--clang/lib/Parse/ParseTentative.cpp6
-rw-r--r--clang/lib/Sema/SemaType.cpp4
-rw-r--r--clang/test/Parser/cxx-ambig-decl-expr.cpp4
-rw-r--r--clang/test/Parser/cxx0x-decl.cpp2
9 files changed, 52 insertions, 11 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 6b722929f60..93b9356e3a6 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -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);
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 2e7411337bf..0baaa76f286 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -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:
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 127e18439b8..9e3e8ac0208 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -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()) {
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 68b73ca1d25..172950fc673 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -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,
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 914f6f3613b..ecb36fe668f 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -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();
}
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index 5c206f4eab9..10c084b66da 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -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);
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index af060cf21b5..6984505d98f 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -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.
diff --git a/clang/test/Parser/cxx-ambig-decl-expr.cpp b/clang/test/Parser/cxx-ambig-decl-expr.cpp
index feb185fbe3f..7bf08b02c4f 100644
--- a/clang/test/Parser/cxx-ambig-decl-expr.cpp
+++ b/clang/test/Parser/cxx-ambig-decl-expr.cpp
@@ -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'}}
diff --git a/clang/test/Parser/cxx0x-decl.cpp b/clang/test/Parser/cxx0x-decl.cpp
index 2b253c019c9..1eaf84a471e 100644
--- a/clang/test/Parser/cxx0x-decl.cpp
+++ b/clang/test/Parser/cxx0x-decl.cpp
@@ -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}}
}
OpenPOWER on IntegriCloud