diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-09-04 06:33:52 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-09-04 06:33:52 +0000 |
commit | 45f965581935791a018df829a14dff53c1dd8f47 (patch) | |
tree | 49fb91aadae8ae184b90210edd16e929da76990b | |
parent | b117a60f7684261ddc8c8f14e8ef8a827e6af814 (diff) |
Parse extern templates, pass that information all the way to Sema,
then drop it on the floor.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80989 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Parse/Action.h | 14 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 12 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 14 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 8 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 10 | ||||
-rw-r--r-- | test/SemaTemplate/extern-templates.cpp | 20 |
8 files changed, 81 insertions, 14 deletions
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 370fed9966..c7fde9c2cc 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -1749,6 +1749,9 @@ public: /// /// \param S the current scope /// + /// \param ExternLoc the location of the 'extern' keyword that specifies that + /// this is an extern template (if any). + /// /// \param TemplateLoc the location of the 'template' keyword that /// specifies that this is an explicit instantiation. /// @@ -1774,7 +1777,9 @@ public: /// /// \param Attr attributes that apply to this instantiation. virtual DeclResult - ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, + ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, @@ -1804,6 +1809,9 @@ public: /// /// \param S the current scope /// + /// \param ExternLoc the location of the 'extern' keyword that specifies that + /// this is an extern template (if any). + /// /// \param TemplateLoc the location of the 'template' keyword that /// specifies that this is an explicit instantiation. /// @@ -1829,7 +1837,9 @@ public: /// /// \param Attr attributes that apply to this instantiation. virtual DeclResult - ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, + ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 641b09947b..dd1036e861 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -607,9 +607,10 @@ private: : Kind(isSpecialization? ExplicitSpecialization : Template), TemplateParams(TemplateParams) { } - explicit ParsedTemplateInfo(SourceLocation TemplateLoc) + explicit ParsedTemplateInfo(SourceLocation ExternLoc, + SourceLocation TemplateLoc) : Kind(ExplicitInstantiation), TemplateParams(0), - TemplateLoc(TemplateLoc) { } + ExternLoc(ExternLoc), TemplateLoc(TemplateLoc) { } /// \brief The kind of template we are parsing. enum { @@ -627,6 +628,10 @@ private: /// and explicit specializations. TemplateParameterLists *TemplateParams; + /// \brief The location of the 'extern' keyword, if any, for an explicit + /// instantiation + SourceLocation ExternLoc; + /// \brief The location of the 'template' keyword, for an explicit /// instantiation. SourceLocation TemplateLoc; @@ -1241,7 +1246,8 @@ private: TemplateArgIsTypeList &TemplateArgIsType, TemplateArgLocationList &TemplateArgLocations); void *ParseTemplateArgument(bool &ArgIsType); - DeclPtrTy ParseExplicitInstantiation(SourceLocation TemplateLoc, + DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc, + SourceLocation TemplateLoc, SourceLocation &DeclEnd); //===--------------------------------------------------------------------===// diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 385b805113..c82f6a4114 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -638,6 +638,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // This is an explicit instantiation of a class template. TagOrTempResult = Actions.ActOnExplicitInstantiation(CurScope, + TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, TagType, StartLoc, @@ -734,6 +735,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // TagOrTempResult = Actions.ActOnExplicitInstantiation(CurScope, + TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, TagType, StartLoc, SS, Name, NameLoc, Attr); diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 34cabfd7ad..40de81a883 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -25,7 +25,8 @@ Parser::ParseDeclarationStartingWithTemplate(unsigned Context, SourceLocation &DeclEnd, AccessSpecifier AS) { if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) - return ParseExplicitInstantiation(ConsumeToken(), DeclEnd); + return ParseExplicitInstantiation(SourceLocation(), ConsumeToken(), + DeclEnd); return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS); } @@ -186,7 +187,6 @@ Parser::ParseSingleDeclarationAfterTemplate( // Parse the declaration specifiers. DeclSpec DS; - // FIXME: Pass TemplateLoc through for explicit template instantiations ParseDeclarationSpecifiers(DS, TemplateInfo, AS); if (Tok.is(tok::semi)) { @@ -871,11 +871,15 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs, /// (C++ [temp.explicit]). /// /// explicit-instantiation: -/// 'template' declaration +/// 'extern' [opt] 'template' declaration +/// +/// Note that the 'extern' is a GNU extension and C++0x feature. Parser::DeclPtrTy -Parser::ParseExplicitInstantiation(SourceLocation TemplateLoc, +Parser::ParseExplicitInstantiation(SourceLocation ExternLoc, + SourceLocation TemplateLoc, SourceLocation &DeclEnd) { return ParseSingleDeclarationAfterTemplate(Declarator::FileContext, - ParsedTemplateInfo(TemplateLoc), + ParsedTemplateInfo(ExternLoc, + TemplateLoc), DeclEnd, AS_none); } diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 36d5db599d..8572d32686 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -391,6 +391,7 @@ void Parser::ParseTranslationUnit() { /// [C++0x] empty-declaration: /// ';' /// +/// [C++0x/GNU] 'extern' 'template' declaration Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() { DeclPtrTy SingleDecl; switch (Tok.getKind()) { @@ -452,6 +453,20 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() { SourceLocation DeclEnd; return ParseDeclaration(Declarator::FileContext, DeclEnd); } + case tok::kw_extern: + if (getLang().CPlusPlus && NextToken().is(tok::kw_template)) { + // Extern templates + SourceLocation ExternLoc = ConsumeToken(); + SourceLocation TemplateLoc = ConsumeToken(); + SourceLocation DeclEnd; + return Actions.ConvertDeclToDeclGroup( + ParseExplicitInstantiation(ExternLoc, TemplateLoc, DeclEnd)); + } + + // FIXME: Detect C++ linkage specifications here? + + // Fall through to handle other declarations or function definitions. + default: // We can't tell whether this is a function-definition or declaration yet. return ParseDeclarationOrFunctionDefinition(); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index f1e4968fd2..78e71bcab8 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2454,7 +2454,9 @@ public: Declarator &D); virtual DeclResult - ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, + ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, @@ -2467,7 +2469,9 @@ public: AttributeList *Attr); virtual DeclResult - ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, + ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 8eaa9fb397..76b6d7ecaa 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2849,8 +2849,11 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, } // Explicit instantiation of a class template specialization +// FIXME: Implement extern template semantics Sema::DeclResult -Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, +Sema::ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, @@ -3034,8 +3037,11 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, } // Explicit instantiation of a member class of a class template. +// FIXME: Implement extern template semantics. Sema::DeclResult -Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, +Sema::ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, diff --git a/test/SemaTemplate/extern-templates.cpp b/test/SemaTemplate/extern-templates.cpp new file mode 100644 index 0000000000..3fce20c17b --- /dev/null +++ b/test/SemaTemplate/extern-templates.cpp @@ -0,0 +1,20 @@ +// RUN: clang-cc -fsyntax-only %s + +template<typename T> +class X0 { +public: + void f(T t); +}; + +template<typename T> +void X0<T>::f(T t) { + t = 17; +} + +// FIXME: Later, we'll want to write an explicit template +// declaration (extern template) for X0<int*>, then try to +// call X0<int*>::f. The translation unit should succeed, +// because we're not allowed to instantiate the out-of-line +// definition of X0<T>::f. For now, this is just a parsing +// test. +extern template class X0<int>; |