diff options
author | Francois Pichet <pichet2000@gmail.com> | 2011-04-22 22:18:13 +0000 |
---|---|---|
committer | Francois Pichet <pichet2000@gmail.com> | 2011-04-22 22:18:13 +0000 |
commit | 8387e2a41eef6fa17fb140a18c29b6eee9dd2b8a (patch) | |
tree | 56e18603554b83fdb5ca1ccd11b550e4d972c81d /lib/Sema | |
parent | 64089cece350472c04b420c497ae391443353325 (diff) |
Add -fdelayed-template-parsing option. Using this option all templated function definitions are parsed at the end of the translation unit only if it is required by an actual instantiation. As such all the symbols of the TU are available during name lookup.
Using this flag is necessary for compatibility with Microsoft template code.
This also provides some parsing speed improvement.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130022 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 19 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 15 |
5 files changed, 62 insertions, 1 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 403cf6246c..dc1270243d 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -142,6 +142,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), PackContext(0), VisContext(0), + LateTemplateParser(0), OpaqueParser(0), IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0), GlobalNewDeleteDeclared(false), CompleteTranslationUnit(CompleteTranslationUnit), diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index e506dd502a..2abc6dafa8 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5748,8 +5748,13 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { // See if this is a redefinition. // But don't complain if we're in GNU89 mode and the previous definition // was an extern inline function. + + // FIXME: This code doesn't complain about multiple definition for late + // parsed template function. + bool IsLateParsingRedefinition = LateTemplateParser && + FD->isLateTemplateParsed(); const FunctionDecl *Definition; - if (FD->hasBody(Definition) && + if (FD->hasBody(Definition) && !IsLateParsingRedefinition && !canRedefineFunction(Definition, getLangOptions())) { if (getLangOptions().GNUMode && Definition->isInlineSpecified() && Definition->getStorageClass() == SC_Extern) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 53a7c73998..5f3f600c8c 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3166,6 +3166,25 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { } } +void Sema::ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D) { + if (!D) + return; + + int NumParamList = D->getNumTemplateParameterLists(); + for (int i = 0; i < NumParamList; i++) { + TemplateParameterList* Params = D->getTemplateParameterList(i); + for (TemplateParameterList::iterator Param = Params->begin(), + ParamEnd = Params->end(); + Param != ParamEnd; ++Param) { + NamedDecl *Named = cast<NamedDecl>(*Param); + if (Named->getDeclName()) { + S->AddDecl(Named); + IdResolver.AddDecl(Named); + } + } + } +} + void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) { if (!D) return; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 49e4a87fd1..08eb654236 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -6381,3 +6381,24 @@ Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, Out << ']'; return Out.str(); } + +void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag) { + if (!FD) + return; + FD->setLateTemplateParsed(Flag); +} + +bool Sema::IsInsideALocalClassWithinATemplateFunction() { + DeclContext *DC = CurContext; + + while (DC) { + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) { + const FunctionDecl *FD = RD->isLocalClass(); + return (FD && FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate); + } else if (DC->isTranslationUnit() || DC->isNamespace()) + return false; + + DC = DC->getParent(); + } + return false; +} diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 0ff7ff4d40..588501f50e 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2262,6 +2262,21 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (PatternDecl) Pattern = PatternDecl->getBody(PatternDecl); + // Postpone late parsed template instantiations. + if (PatternDecl->isLateTemplateParsed() && !LateTemplateParser) { + PendingInstantiations.push_back( + std::make_pair(Function, PointOfInstantiation)); + return; + } + + // Call the LateTemplateParser callback if there a need to late parse + // a templated function definition. + if (!Pattern && PatternDecl && PatternDecl->isLateTemplateParsed() && + LateTemplateParser) { + LateTemplateParser(OpaqueParser, (FunctionDecl*)PatternDecl); + Pattern = PatternDecl->getBody(PatternDecl); + } + if (!Pattern) { if (DefinitionRequired) { if (Function->getPrimaryTemplate()) |