aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Parse/ParseTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/ParseTemplate.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Parse/ParseTemplate.cpp244
1 files changed, 65 insertions, 179 deletions
diff --git a/contrib/llvm-project/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm-project/clang/lib/Parse/ParseTemplate.cpp
index 64fe4d50bba2..a5130f56600e 100644
--- a/contrib/llvm-project/clang/lib/Parse/ParseTemplate.cpp
+++ b/contrib/llvm-project/clang/lib/Parse/ParseTemplate.cpp
@@ -36,17 +36,19 @@ unsigned Parser::ReenterTemplateScopes(MultiParseScope &S, Decl *D) {
/// Parse a template declaration, explicit instantiation, or
/// explicit specialization.
-Decl *Parser::ParseDeclarationStartingWithTemplate(
- DeclaratorContext Context, SourceLocation &DeclEnd,
- ParsedAttributes &AccessAttrs, AccessSpecifier AS) {
+Parser::DeclGroupPtrTy
+Parser::ParseDeclarationStartingWithTemplate(DeclaratorContext Context,
+ SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs) {
ObjCDeclContextSwitch ObjCDC(*this);
if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) {
return ParseExplicitInstantiation(Context, SourceLocation(), ConsumeToken(),
- DeclEnd, AccessAttrs, AS);
+ DeclEnd, AccessAttrs,
+ AccessSpecifier::AS_none);
}
return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AccessAttrs,
- AS);
+ AccessSpecifier::AS_none);
}
/// Parse a template declaration or an explicit specialization.
@@ -73,7 +75,7 @@ Decl *Parser::ParseDeclarationStartingWithTemplate(
///
/// explicit-specialization: [ C++ temp.expl.spec]
/// 'template' '<' '>' declaration
-Decl *Parser::ParseTemplateDeclarationOrSpecialization(
+Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization(
DeclaratorContext Context, SourceLocation &DeclEnd,
ParsedAttributes &AccessAttrs, AccessSpecifier AS) {
assert(Tok.isOneOf(tok::kw_export, tok::kw_template) &&
@@ -161,17 +163,20 @@ Decl *Parser::ParseTemplateDeclarationOrSpecialization(
TemplateParams, RAngleLoc, OptionalRequiresClauseConstraintER.get()));
} while (Tok.isOneOf(tok::kw_export, tok::kw_template));
+ ParsedTemplateInfo TemplateInfo(&ParamLists, isSpecialization,
+ LastParamListWasEmpty);
+
// Parse the actual template declaration.
- if (Tok.is(tok::kw_concept))
- return ParseConceptDefinition(
- ParsedTemplateInfo(&ParamLists, isSpecialization,
- LastParamListWasEmpty),
- DeclEnd);
-
- return ParseSingleDeclarationAfterTemplate(
- Context,
- ParsedTemplateInfo(&ParamLists, isSpecialization, LastParamListWasEmpty),
- ParsingTemplateParams, DeclEnd, AccessAttrs, AS);
+ if (Tok.is(tok::kw_concept)) {
+ Decl *ConceptDecl = ParseConceptDefinition(TemplateInfo, DeclEnd);
+ // We need to explicitly pass ConceptDecl to ParsingDeclRAIIObject, so that
+ // delayed diagnostics (e.g. warn_deprecated) have a Decl to work with.
+ ParsingTemplateParams.complete(ConceptDecl);
+ return Actions.ConvertDeclToDeclGroup(ConceptDecl);
+ }
+
+ return ParseDeclarationAfterTemplate(
+ Context, TemplateInfo, ParsingTemplateParams, DeclEnd, AccessAttrs, AS);
}
/// Parse a single declaration that declares a template,
@@ -184,8 +189,8 @@ Decl *Parser::ParseTemplateDeclarationOrSpecialization(
/// declaration. Will be AS_none for namespace-scope declarations.
///
/// \returns the new declaration.
-Decl *Parser::ParseSingleDeclarationAfterTemplate(
- DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,
+Parser::DeclGroupPtrTy Parser::ParseDeclarationAfterTemplate(
+ DeclaratorContext Context, ParsedTemplateInfo &TemplateInfo,
ParsingDeclRAIIObject &DiagsFromTParams, SourceLocation &DeclEnd,
ParsedAttributes &AccessAttrs, AccessSpecifier AS) {
assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
@@ -196,37 +201,29 @@ Decl *Parser::ParseSingleDeclarationAfterTemplate(
Diag(Tok.getLocation(), diag::err_templated_invalid_declaration)
<< TemplateInfo.getSourceRange();
// Parse the static_assert declaration to improve error recovery.
- return ParseStaticAssertDeclaration(DeclEnd);
+ return Actions.ConvertDeclToDeclGroup(
+ ParseStaticAssertDeclaration(DeclEnd));
}
- if (Context == DeclaratorContext::Member) {
- // We are parsing a member template.
- DeclGroupPtrTy D = ParseCXXClassMemberDeclaration(
- AS, AccessAttrs, TemplateInfo, &DiagsFromTParams);
+ // We are parsing a member template.
+ if (Context == DeclaratorContext::Member)
+ return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,
+ &DiagsFromTParams);
- if (!D || !D.get().isSingleDecl())
- return nullptr;
- return D.get().getSingleDecl();
- }
-
- ParsedAttributes prefixAttrs(AttrFactory);
+ ParsedAttributes DeclAttrs(AttrFactory);
ParsedAttributes DeclSpecAttrs(AttrFactory);
// GNU attributes are applied to the declaration specification while the
// standard attributes are applied to the declaration. We parse the two
// attribute sets into different containters so we can apply them during
// the regular parsing process.
- while (MaybeParseCXX11Attributes(prefixAttrs) ||
+ while (MaybeParseCXX11Attributes(DeclAttrs) ||
MaybeParseGNUAttributes(DeclSpecAttrs))
;
- if (Tok.is(tok::kw_using)) {
- auto usingDeclPtr = ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
- prefixAttrs);
- if (!usingDeclPtr || !usingDeclPtr.get().isSingleDecl())
- return nullptr;
- return usingDeclPtr.get().getSingleDecl();
- }
+ if (Tok.is(tok::kw_using))
+ return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
+ DeclAttrs);
// Parse the declaration specifiers, stealing any diagnostics from
// the template parameters.
@@ -239,7 +236,7 @@ Decl *Parser::ParseSingleDeclarationAfterTemplate(
getDeclSpecContextFromDeclaratorContext(Context));
if (Tok.is(tok::semi)) {
- ProhibitAttributes(prefixAttrs);
+ ProhibitAttributes(DeclAttrs);
DeclEnd = ConsumeToken();
RecordDecl *AnonRecord = nullptr;
Decl *Decl = Actions.ParsedFreeStandingDeclSpec(
@@ -252,7 +249,7 @@ Decl *Parser::ParseSingleDeclarationAfterTemplate(
assert(!AnonRecord &&
"Anonymous unions/structs should not be valid with template");
DS.complete(Decl);
- return Decl;
+ return Actions.ConvertDeclToDeclGroup(Decl);
}
if (DS.hasTagDefinition())
@@ -260,125 +257,9 @@ Decl *Parser::ParseSingleDeclarationAfterTemplate(
// Move the attributes from the prefix into the DS.
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
- ProhibitAttributes(prefixAttrs);
-
- // Parse the declarator.
- ParsingDeclarator DeclaratorInfo(*this, DS, prefixAttrs,
- (DeclaratorContext)Context);
- if (TemplateInfo.TemplateParams)
- DeclaratorInfo.setTemplateParameterLists(*TemplateInfo.TemplateParams);
-
- // Turn off usual access checking for template specializations and
- // instantiations.
- // C++20 [temp.spec] 13.9/6.
- // This disables the access checking rules for function template explicit
- // instantiation and explicit specialization:
- // - parameter-list;
- // - template-argument-list;
- // - noexcept-specifier;
- // - dynamic-exception-specifications (deprecated in C++11, removed since
- // C++17).
- bool IsTemplateSpecOrInst =
- (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
- TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
- SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst);
-
- ParseDeclarator(DeclaratorInfo);
-
- if (IsTemplateSpecOrInst)
- SAC.done();
-
- // Error parsing the declarator?
- if (!DeclaratorInfo.hasName()) {
- SkipMalformedDecl();
- return nullptr;
- }
-
- LateParsedAttrList LateParsedAttrs(true);
- if (DeclaratorInfo.isFunctionDeclarator()) {
- if (Tok.is(tok::kw_requires)) {
- CXXScopeSpec &ScopeSpec = DeclaratorInfo.getCXXScopeSpec();
- DeclaratorScopeObj DeclScopeObj(*this, ScopeSpec);
- if (ScopeSpec.isValid() &&
- Actions.ShouldEnterDeclaratorScope(getCurScope(), ScopeSpec))
- DeclScopeObj.EnterDeclaratorScope();
- ParseTrailingRequiresClause(DeclaratorInfo);
- }
+ ProhibitAttributes(DeclAttrs);
- MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);
- }
-
- if (DeclaratorInfo.isFunctionDeclarator() &&
- isStartOfFunctionDefinition(DeclaratorInfo)) {
-
- // Function definitions are only allowed at file scope and in C++ classes.
- // The C++ inline method definition case is handled elsewhere, so we only
- // need to handle the file scope definition case.
- if (Context != DeclaratorContext::File) {
- Diag(Tok, diag::err_function_definition_not_allowed);
- SkipMalformedDecl();
- return nullptr;
- }
-
- if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
- // Recover by ignoring the 'typedef'. This was probably supposed to be
- // the 'typename' keyword, which we should have already suggested adding
- // if it's appropriate.
- Diag(DS.getStorageClassSpecLoc(), diag::err_function_declared_typedef)
- << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
- DS.ClearStorageClassSpecs();
- }
-
- if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
- if (DeclaratorInfo.getName().getKind() !=
- UnqualifiedIdKind::IK_TemplateId) {
- // If the declarator-id is not a template-id, issue a diagnostic and
- // recover by ignoring the 'template' keyword.
- Diag(Tok, diag::err_template_defn_explicit_instantiation) << 0;
- return ParseFunctionDefinition(DeclaratorInfo, ParsedTemplateInfo(),
- &LateParsedAttrs);
- } else {
- SourceLocation LAngleLoc
- = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
- Diag(DeclaratorInfo.getIdentifierLoc(),
- diag::err_explicit_instantiation_with_definition)
- << SourceRange(TemplateInfo.TemplateLoc)
- << FixItHint::CreateInsertion(LAngleLoc, "<>");
-
- // Recover as if it were an explicit specialization.
- TemplateParameterLists FakedParamLists;
- FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
- 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc,
- std::nullopt, LAngleLoc, nullptr));
-
- return ParseFunctionDefinition(
- DeclaratorInfo, ParsedTemplateInfo(&FakedParamLists,
- /*isSpecialization=*/true,
- /*lastParameterListWasEmpty=*/true),
- &LateParsedAttrs);
- }
- }
- return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo,
- &LateParsedAttrs);
- }
-
- // Parse this declaration.
- Decl *ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo,
- TemplateInfo);
-
- if (Tok.is(tok::comma)) {
- Diag(Tok, diag::err_multiple_template_declarators)
- << (int)TemplateInfo.Kind;
- SkipUntil(tok::semi);
- return ThisDecl;
- }
-
- // Eat the semi colon after the declaration.
- ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
- if (LateParsedAttrs.size() > 0)
- ParseLexedAttributeList(LateParsedAttrs, ThisDecl, true, false);
- DeclaratorInfo.complete(ThisDecl);
- return ThisDecl;
+ return ParseDeclGroup(DS, Context, DeclAttrs, TemplateInfo, &DeclEnd);
}
/// \brief Parse a single declaration that declares a concept.
@@ -436,10 +317,11 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,
return nullptr;
}
- IdentifierInfo *Id = Result.Identifier;
+ const IdentifierInfo *Id = Result.Identifier;
SourceLocation IdLoc = Result.getBeginLoc();
- DiagnoseAndSkipCXX11Attributes();
+ ParsedAttributes Attrs(AttrFactory);
+ MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);
if (!TryConsumeToken(tok::equal)) {
Diag(Tok.getLocation(), diag::err_expected) << tok::equal;
@@ -458,8 +340,8 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,
ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
Expr *ConstraintExpr = ConstraintExprResult.get();
return Actions.ActOnConceptDefinition(getCurScope(),
- *TemplateInfo.TemplateParams,
- Id, IdLoc, ConstraintExpr);
+ *TemplateInfo.TemplateParams, Id, IdLoc,
+ ConstraintExpr, Attrs);
}
/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
@@ -856,7 +738,12 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
// we introduce the type parameter into the local scope.
SourceLocation EqualLoc;
ParsedType DefaultArg;
+ std::optional<DelayTemplateIdDestructionRAII> DontDestructTemplateIds;
if (TryConsumeToken(tok::equal, EqualLoc)) {
+ // The default argument might contain a lambda declaration; avoid destroying
+ // parsed template ids at the end of that declaration because they can be
+ // used in a type constraint later.
+ DontDestructTemplateIds.emplace(*this, /*DelayTemplateIdDestruction=*/true);
// The default argument may declare template parameters, notably
// if it contains a generic lambda, so we need to increase
// the template depth as these parameters would not be instantiated
@@ -928,10 +815,12 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,
// identifier, comma, or greater. Provide a fixit if the identifier, comma,
// or greater appear immediately or after 'struct'. In the latter case,
// replace the keyword with 'class'.
+ bool TypenameKeyword = false;
if (!TryConsumeToken(tok::kw_class)) {
bool Replace = Tok.isOneOf(tok::kw_typename, tok::kw_struct);
const Token &Next = Tok.is(tok::kw_struct) ? NextToken() : Tok;
if (Tok.is(tok::kw_typename)) {
+ TypenameKeyword = true;
Diag(Tok.getLocation(),
getLangOpts().CPlusPlus17
? diag::warn_cxx14_compat_template_template_param_typename
@@ -1001,10 +890,9 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,
}
}
- return Actions.ActOnTemplateTemplateParameter(getCurScope(), TemplateLoc,
- ParamList, EllipsisLoc,
- ParamName, NameLoc, Depth,
- Position, EqualLoc, DefaultArg);
+ return Actions.ActOnTemplateTemplateParameter(
+ getCurScope(), TemplateLoc, ParamList, TypenameKeyword, EllipsisLoc,
+ ParamName, NameLoc, Depth, Position, EqualLoc, DefaultArg);
}
/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
@@ -1019,7 +907,8 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
// FIXME: The type should probably be restricted in some way... Not all
// declarators (parts of declarators?) are accepted for parameters.
DeclSpec DS(AttrFactory);
- ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
+ ParsedTemplateInfo TemplateInfo;
+ ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none,
DeclSpecContext::DSC_template_param);
// Parse this as a typename.
@@ -1412,7 +1301,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
// later.
Tok.setKind(tok::annot_template_id);
- IdentifierInfo *TemplateII =
+ const IdentifierInfo *TemplateII =
TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier
? TemplateName.Identifier
: nullptr;
@@ -1652,8 +1541,8 @@ bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
if (!Template)
return QualType();
CalledSignatureHelp = true;
- return Actions.ProduceTemplateArgumentSignatureHelp(Template, TemplateArgs,
- OpenLoc);
+ return Actions.CodeCompletion().ProduceTemplateArgumentSignatureHelp(
+ Template, TemplateArgs, OpenLoc);
};
do {
@@ -1686,19 +1575,16 @@ bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
/// 'extern' [opt] 'template' declaration
///
/// Note that the 'extern' is a GNU extension and C++11 feature.
-Decl *Parser::ParseExplicitInstantiation(DeclaratorContext Context,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- SourceLocation &DeclEnd,
- ParsedAttributes &AccessAttrs,
- AccessSpecifier AS) {
+Parser::DeclGroupPtrTy Parser::ParseExplicitInstantiation(
+ DeclaratorContext Context, SourceLocation ExternLoc,
+ SourceLocation TemplateLoc, SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs, AccessSpecifier AS) {
// This isn't really required here.
ParsingDeclRAIIObject
ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent);
-
- return ParseSingleDeclarationAfterTemplate(
- Context, ParsedTemplateInfo(ExternLoc, TemplateLoc),
- ParsingTemplateParams, DeclEnd, AccessAttrs, AS);
+ ParsedTemplateInfo TemplateInfo(ExternLoc, TemplateLoc);
+ return ParseDeclarationAfterTemplate(
+ Context, TemplateInfo, ParsingTemplateParams, DeclEnd, AccessAttrs, AS);
}
SourceRange Parser::ParsedTemplateInfo::getSourceRange() const {