aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-01-24 22:00:03 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-01-24 22:00:03 +0000
commit480093f4440d54b30b3025afeac24b48f2ba7a2e (patch)
tree162e72994062888647caf0d875428db9445491a8 /contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp
parent489b1cf2ecf5b9b4a394857987014bfb09067726 (diff)
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff)
Notes
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp151
1 files changed, 110 insertions, 41 deletions
diff --git a/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp
index b248d7582d84..69a3ed9cbad7 100644
--- a/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp
+++ b/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp
@@ -2014,6 +2014,9 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
return nullptr;
}
+ if (Tok.is(tok::kw_requires))
+ ParseTrailingRequiresClause(D);
+
// Save late-parsed attributes for now; they need to be parsed in the
// appropriate function scope after the function Decl has been constructed.
// These will be parsed in ParseFunctionDefinition or ParseLexedAttrList.
@@ -2165,6 +2168,12 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
ParseDeclarator(D);
if (!D.isInvalidType()) {
+ // C++2a [dcl.decl]p1
+ // init-declarator:
+ // declarator initializer[opt]
+ // declarator requires-clause
+ if (Tok.is(tok::kw_requires))
+ ParseTrailingRequiresClause(D);
Decl *ThisDecl = ParseDeclarationAfterDeclarator(D);
D.complete(ThisDecl);
if (ThisDecl)
@@ -2197,7 +2206,7 @@ bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) {
// If a simple-asm-expr is present, parse it.
if (Tok.is(tok::kw_asm)) {
SourceLocation Loc;
- ExprResult AsmLabel(ParseSimpleAsm(&Loc));
+ ExprResult AsmLabel(ParseSimpleAsm(/*ForAsmLabel*/ true, &Loc));
if (AsmLabel.isInvalid()) {
SkipUntil(tok::semi, StopBeforeMatch);
return true;
@@ -2349,7 +2358,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
<< 0 /* default */;
else
- Diag(ConsumeToken(), diag::err_default_special_members);
+ Diag(ConsumeToken(), diag::err_default_special_members)
+ << getLangOpts().CPlusPlus2a;
} else {
InitializerScopeRAII InitScope(*this, D, ThisDecl);
@@ -3948,9 +3958,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
PrevSpec = Tok.getIdentifierInfo()->getNameStart();
isInvalid = true;
break;
- };
+ }
LLVM_FALLTHROUGH;
case tok::kw_private:
+ // It's fine (but redundant) to check this for __generic on the
+ // fallthrough path; we only form the __generic token in OpenCL mode.
+ if (!getLangOpts().OpenCL)
+ goto DoneWithDeclSpec;
+ LLVM_FALLTHROUGH;
case tok::kw___private:
case tok::kw___global:
case tok::kw___local:
@@ -5106,6 +5121,13 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
return !DisambiguatingWithExpression ||
!isStartOfObjCClassMessageMissingOpenBracket();
+ // placeholder-type-specifier
+ case tok::annot_template_id: {
+ TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
+ return TemplateId->Kind == TNK_Concept_template &&
+ (NextToken().is(tok::kw_auto) || NextToken().is(tok::kw_decltype));
+ }
+
case tok::kw___declspec:
case tok::kw___cdecl:
case tok::kw___stdcall:
@@ -6026,6 +6048,22 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
PrototypeScope.Exit();
} else if (Tok.is(tok::l_square)) {
ParseBracketDeclarator(D);
+ } else if (Tok.is(tok::kw_requires) && D.hasGroupingParens()) {
+ // This declarator is declaring a function, but the requires clause is
+ // in the wrong place:
+ // void (f() requires true);
+ // instead of
+ // void f() requires true;
+ // or
+ // void (f()) requires true;
+ Diag(Tok, diag::err_requires_clause_inside_parens);
+ ConsumeToken();
+ ExprResult TrailingRequiresClause = Actions.CorrectDelayedTyposInExpr(
+ ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true));
+ if (TrailingRequiresClause.isUsable() && D.isFunctionDeclarator() &&
+ !D.hasTrailingRequiresClause())
+ // We're already ill-formed if we got here but we'll accept it anyway.
+ D.setTrailingRequiresClause(TrailingRequiresClause.get());
} else {
break;
}
@@ -6206,6 +6244,47 @@ void Parser::ParseParenDeclarator(Declarator &D) {
PrototypeScope.Exit();
}
+void Parser::InitCXXThisScopeForDeclaratorIfRelevant(
+ const Declarator &D, const DeclSpec &DS,
+ llvm::Optional<Sema::CXXThisScopeRAII> &ThisScope) {
+ // C++11 [expr.prim.general]p3:
+ // If a declaration declares a member function or member function
+ // template of a class X, the expression this is a prvalue of type
+ // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+ // and the end of the function-definition, member-declarator, or
+ // declarator.
+ // FIXME: currently, "static" case isn't handled correctly.
+ bool IsCXX11MemberFunction = getLangOpts().CPlusPlus11 &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+ (D.getContext() == DeclaratorContext::MemberContext
+ ? !D.getDeclSpec().isFriendSpecified()
+ : D.getContext() == DeclaratorContext::FileContext &&
+ D.getCXXScopeSpec().isValid() &&
+ Actions.CurContext->isRecord());
+ if (!IsCXX11MemberFunction)
+ return;
+
+ Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers());
+ if (D.getDeclSpec().hasConstexprSpecifier() && !getLangOpts().CPlusPlus14)
+ Q.addConst();
+ // FIXME: Collect C++ address spaces.
+ // If there are multiple different address spaces, the source is invalid.
+ // Carry on using the first addr space for the qualifiers of 'this'.
+ // The diagnostic will be given later while creating the function
+ // prototype for the method.
+ if (getLangOpts().OpenCLCPlusPlus) {
+ for (ParsedAttr &attr : DS.getAttributes()) {
+ LangAS ASIdx = attr.asOpenCLLangAS();
+ if (ASIdx != LangAS::Default) {
+ Q.addAddressSpace(ASIdx);
+ break;
+ }
+ }
+ }
+ ThisScope.emplace(Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), Q,
+ IsCXX11MemberFunction);
+}
+
/// ParseFunctionDeclarator - We are after the identifier and have parsed the
/// declarator D up to a paren, which indicates that we are parsing function
/// arguments.
@@ -6219,7 +6298,8 @@ void Parser::ParseParenDeclarator(Declarator &D) {
///
/// For C++, after the parameter-list, it also parses the cv-qualifier-seq[opt],
/// (C++11) ref-qualifier[opt], exception-specification[opt],
-/// (C++11) attribute-specifier-seq[opt], and (C++11) trailing-return-type[opt].
+/// (C++11) attribute-specifier-seq[opt], (C++11) trailing-return-type[opt] and
+/// (C++2a) the trailing requires-clause.
///
/// [C++11] exception-specification:
/// dynamic-exception-specification
@@ -6314,43 +6394,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc))
EndLoc = RefQualifierLoc;
- // C++11 [expr.prim.general]p3:
- // If a declaration declares a member function or member function
- // template of a class X, the expression this is a prvalue of type
- // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
- // and the end of the function-definition, member-declarator, or
- // declarator.
- // FIXME: currently, "static" case isn't handled correctly.
- bool IsCXX11MemberFunction =
- getLangOpts().CPlusPlus11 &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
- (D.getContext() == DeclaratorContext::MemberContext
- ? !D.getDeclSpec().isFriendSpecified()
- : D.getContext() == DeclaratorContext::FileContext &&
- D.getCXXScopeSpec().isValid() &&
- Actions.CurContext->isRecord());
-
- Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers());
- if (D.getDeclSpec().hasConstexprSpecifier() && !getLangOpts().CPlusPlus14)
- Q.addConst();
- // FIXME: Collect C++ address spaces.
- // If there are multiple different address spaces, the source is invalid.
- // Carry on using the first addr space for the qualifiers of 'this'.
- // The diagnostic will be given later while creating the function
- // prototype for the method.
- if (getLangOpts().OpenCLCPlusPlus) {
- for (ParsedAttr &attr : DS.getAttributes()) {
- LangAS ASIdx = attr.asOpenCLLangAS();
- if (ASIdx != LangAS::Default) {
- Q.addAddressSpace(ASIdx);
- break;
- }
- }
- }
-
- Sema::CXXThisScopeRAII ThisScope(
- Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), Q,
- IsCXX11MemberFunction);
+ llvm::Optional<Sema::CXXThisScopeRAII> ThisScope;
+ InitCXXThisScopeForDeclaratorIfRelevant(D, DS, ThisScope);
// Parse exception-specification[opt].
bool Delayed = D.isFirstDeclarationOfMember() &&
@@ -6565,6 +6610,19 @@ void Parser::ParseParameterDeclarationClause(
ParsedAttributes &FirstArgAttrs,
SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
SourceLocation &EllipsisLoc) {
+
+ // Avoid exceeding the maximum function scope depth.
+ // See https://bugs.llvm.org/show_bug.cgi?id=19607
+ // Note Sema::ActOnParamDeclarator calls ParmVarDecl::setScopeInfo with
+ // getFunctionPrototypeDepth() - 1.
+ if (getCurScope()->getFunctionPrototypeDepth() - 1 >
+ ParmVarDecl::getMaxFunctionScopeDepth()) {
+ Diag(Tok.getLocation(), diag::err_function_scope_depth_exceeded)
+ << ParmVarDecl::getMaxFunctionScopeDepth();
+ cutOffParsing();
+ return;
+ }
+
do {
// FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
// before deciding this was a parameter-declaration-clause.
@@ -6605,6 +6663,17 @@ void Parser::ParseParameterDeclarationClause(
// Parse GNU attributes, if present.
MaybeParseGNUAttributes(ParmDeclarator);
+ if (Tok.is(tok::kw_requires)) {
+ // User tried to define a requires clause in a parameter declaration,
+ // which is surely not a function declaration.
+ // void f(int (*g)(int, int) requires true);
+ Diag(Tok,
+ diag::err_requires_clause_on_declarator_not_declaring_a_function);
+ ConsumeToken();
+ Actions.CorrectDelayedTyposInExpr(
+ ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true));
+ }
+
// Remember this parsed parameter in ParamInfo.
IdentifierInfo *ParmII = ParmDeclarator.getIdentifier();