From c85ed7e4a2a1f42a07e4940f38d7f365b662a1af Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 23 Oct 2013 21:31:20 +0000 Subject: [PATCH] Parse: Disable delayed template parsing for constexpr functions Commit r191484 treated constexpr function templates as normal function templates with respect to delaying their parsing. However, this is unnecessarily restrictive because there is no compatibility concern with constexpr, MSVC doesn't support it. Instead, simply disable delayed template parsing for constexpr function templates. This largely reverts the changes made in r191484 but keeps it's unit test. This fixes PR17661. llvm-svn: 193274 --- clang/lib/Parse/ParseCXXInlineMethods.cpp | 1 + clang/lib/Parse/Parser.cpp | 6 +++--- clang/lib/Sema/SemaExpr.cpp | 8 +++----- clang/test/Parser/DelayedTemplateParsing.cpp | 7 +++++++ 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 6bab7988cf0b..863a09e89d34 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -115,6 +115,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, // the tokens and store them for parsing at the end of the translation unit. if (getLangOpts().DelayedTemplateParsing && DefinitionKind == FDK_Definition && + !D.getDeclSpec().isConstexprSpecified() && ((Actions.CurContext->isDependentContext() || (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && TemplateInfo.Kind != ParsedTemplateInfo::ExplicitSpecialization)) && diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 9b6c97ac195f..d95546af8ab5 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -990,9 +990,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // In delayed template parsing mode, for function template we consume the // tokens and store them for late parsing at the end of the translation unit. - if (getLangOpts().DelayedTemplateParsing && - Tok.isNot(tok::equal) && - TemplateInfo.Kind == ParsedTemplateInfo::Template) { + if (getLangOpts().DelayedTemplateParsing && Tok.isNot(tok::equal) && + TemplateInfo.Kind == ParsedTemplateInfo::Template && + !D.getDeclSpec().isConstexprSpecified()) { MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams); ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 56eeab3bea37..c842ed035d88 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -11088,8 +11088,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { // However, they cannot be referenced if they are deleted, and they are // deleted whenever the implicit definition of the special member would // fail. - if (!(Func->isConstexpr() && !getLangOpts().DelayedTemplateParsing) || - Func->getBody()) + if (!Func->isConstexpr() || Func->getBody()) return; CXXMethodDecl *MD = dyn_cast(Func); if (!Func->isImplicitlyInstantiable() && (!MD || MD->isUserProvided())) @@ -11180,14 +11179,13 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { } } - if (!AlreadyInstantiated || - (Func->isConstexpr() && !getLangOpts().DelayedTemplateParsing)) { + if (!AlreadyInstantiated || Func->isConstexpr()) { if (isa(Func->getDeclContext()) && cast(Func->getDeclContext())->isLocalClass() && ActiveTemplateInstantiations.size()) PendingLocalImplicitInstantiations.push_back( std::make_pair(Func, PointOfInstantiation)); - else if (Func->isConstexpr() && !getLangOpts().DelayedTemplateParsing) + else if (Func->isConstexpr()) // Do not defer instantiations of constexpr functions, to avoid the // expression evaluator needing to call back into Sema if it sees a // call to such a function. diff --git a/clang/test/Parser/DelayedTemplateParsing.cpp b/clang/test/Parser/DelayedTemplateParsing.cpp index 201fe1b466db..73128c49f247 100644 --- a/clang/test/Parser/DelayedTemplateParsing.cpp +++ b/clang/test/Parser/DelayedTemplateParsing.cpp @@ -114,3 +114,10 @@ void LLVMBuildStructGEP() { CreateConstInBoundsGEP2_32(); } } +namespace PR17661 { +template +constexpr T Fun(T A) { return T(0); } + +constexpr int Var = Fun(20); +} +