[cfe-commits] r61208 - in /cfe/trunk: include/clang/Basic/TokenKinds.def include/clang/Lex/Token.h include/clang/Parse/Action.h include/clang/Parse/Ownership.h include/clang/Parse/Parser.h lib/Parse/MinimalAction.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseTemplate.cpp lib/Parse/Parser.cpp lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp test/SemaCXX/template-specialization.cpp test/SemaObjCXX/overload.mm
Douglas Gregor
dgregor at apple.com
Thu Dec 18 11:37:41 PST 2008
Author: dgregor
Date: Thu Dec 18 13:37:40 2008
New Revision: 61208
URL: http://llvm.org/viewvc/llvm-project?rev=61208&view=rev
Log:
Ultrasimplistic sketch for the parsing of C++ template-ids. This won't
become useful or correct until we (1) parse template arguments
correctly, (2) have some way to turn template-ids into types,
declarators, etc., and (3) have a real representation of templates.
Added:
cfe/trunk/test/SemaCXX/template-specialization.cpp
Modified:
cfe/trunk/include/clang/Basic/TokenKinds.def
cfe/trunk/include/clang/Lex/Token.h
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/Ownership.h
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/MinimalAction.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseTemplate.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/SemaObjCXX/overload.mm
Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=61208&r1=61207&r2=61208&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Thu Dec 18 13:37:40 2008
@@ -369,9 +369,12 @@
// bycopy/byref/in/inout/oneway/out?
ANNOTATION(cxxscope) // annotation for a C++ scope spec, e.g. "::foo::bar::"
-ANNOTATION(qualtypename) // annotation for a C typedef name, or a C++ (possibly
- // qualified) typename, e.g. "foo::MyClass"
-
+ANNOTATION(qualtypename) // annotation for a C typedef name, a C++ (possibly
+ // qualified) typename, e.g. "foo::MyClass", or
+ // template-id that names a type ("std::vector<int>")
+ANNOTATION(template_id) // annotation for a C++ template-id that names a
+ // function template specialization (not a type),
+ // e.g., "std::swap<int>"
#undef ANNOTATION
#undef OBJC2_AT_KEYWORD
#undef OBJC1_AT_KEYWORD
Modified: cfe/trunk/include/clang/Lex/Token.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Token.h?rev=61208&r1=61207&r2=61208&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Token.h (original)
+++ cfe/trunk/include/clang/Lex/Token.h Thu Dec 18 13:37:40 2008
@@ -78,7 +78,9 @@
bool isNot(tok::TokenKind K) const { return Kind != (unsigned) K; }
bool isAnnotationToken() const {
- return is(tok::annot_qualtypename) || is(tok::annot_cxxscope);
+ return is(tok::annot_qualtypename) ||
+ is(tok::annot_cxxscope) ||
+ is(tok::annot_template_id);
}
/// getLocation - Return a source location identifier for the specified
@@ -211,6 +213,28 @@
bool FoundElse;
};
+/// TemplateIdAnnotation - Information about a template-id annotation
+/// token, which contains the template declaration, template
+/// arguments, and the source locations for important tokens.
+struct TemplateIdAnnotation {
+ /// TemplateNameLoc - The location of the template name within the
+ /// source.
+ SourceLocation TemplateNameLoc;
+
+ /// Template - The declaration of the template corresponding to the
+ /// template-name. This is an Action::DeclTy*.
+ void *Template;
+
+ /// LAngleLoc - The location of the '<' before the template argument
+ /// list.
+ SourceLocation LAngleLoc;
+
+ /// NumArgs - The number of template arguments. The arguments
+ /// themselves are Action::TemplateArgTy pointers allocated directly
+ /// following the TemplateIdAnnotation structure.
+ unsigned NumArgs;
+};
+
} // end namespace clang
#endif
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=61208&r1=61207&r2=61208&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Thu Dec 18 13:37:40 2008
@@ -63,6 +63,7 @@
typedef void BaseTy;
typedef void MemInitTy;
typedef void CXXScopeTy;
+ typedef void TemplateArgTy;
/// Expr/Stmt/Type/BaseResult - Provide a unique type to wrap
/// ExprTy/StmtTy/TypeTy/BaseTy, providing strong typing and
@@ -76,27 +77,40 @@
/// Same, but with ownership.
typedef ASTOwningResult<&ActionBase::DeleteExpr> OwningExprResult;
typedef ASTOwningResult<&ActionBase::DeleteStmt> OwningStmtResult;
+ typedef ASTOwningResult<&ActionBase::DeleteTemplateArg>
+ OwningTemplateArgResult;
// Note that these will replace ExprResult and StmtResult when the transition
// is complete.
/// Single expressions or statements as arguments.
typedef ASTOwningPtr<&ActionBase::DeleteExpr> ExprArg;
typedef ASTOwningPtr<&ActionBase::DeleteStmt> StmtArg;
+ typedef ASTOwningPtr<&ActionBase::DeleteTemplateArg> TemplateArgArg;
/// Multiple expressions or statements as arguments.
typedef ASTMultiPtr<&ActionBase::DeleteExpr> MultiExprArg;
typedef ASTMultiPtr<&ActionBase::DeleteStmt> MultiStmtArg;
-
+ typedef ASTMultiPtr<&ActionBase::DeleteTemplateArg> MultiTemplateArgArg;
// Utilities for Action implementations to return smart results.
OwningExprResult ExprError() { return OwningExprResult(*this, true); }
OwningStmtResult StmtError() { return OwningStmtResult(*this, true); }
+ OwningTemplateArgResult TemplateArgError() {
+ return OwningTemplateArgResult(*this, true);
+ }
+
OwningExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); }
OwningStmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); }
+ OwningTemplateArgResult TemplateArgError(const DiagnosticBuilder&) {
+ return TemplateArgError();
+ }
OwningExprResult ExprEmpty() { return OwningExprResult(*this, false); }
OwningStmtResult StmtEmpty() { return OwningStmtResult(*this, false); }
+ OwningTemplateArgResult TemplateArgEmpty() {
+ return OwningTemplateArgResult(*this, false);
+ }
/// Statistics.
virtual void PrintStats() const {}
@@ -117,6 +131,14 @@
virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS = 0) = 0;
+ /// isTemplateName - Determines whether the identifier II is a
+ /// template name in the current scope, and returns the template
+ /// declaration if II names a template. An optional CXXScope can be
+ /// passed to indicate the C++ scope in which the identifier will be
+ /// found.
+ virtual DeclTy *isTemplateName(IdentifierInfo &II, Scope *S,
+ const CXXScopeSpec *SS = 0) = 0;
+
/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
/// global scope ('::').
virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S,
@@ -918,6 +940,8 @@
return 0;
}
+
+
//===----------------------- Obj-C Declarations -------------------------===//
// ActOnStartClassInterface - this action is called immediately after parsing
@@ -1164,6 +1188,14 @@
virtual bool isCurrentClassName(const IdentifierInfo& II, Scope *S,
const CXXScopeSpec *SS);
+ /// isTemplateName - Determines whether the identifier II is a
+ /// template name in the current scope, and returns the template
+ /// declaration if II names a template. An optional CXXScope can be
+ /// passed to indicate the C++ scope in which the identifier will be
+ /// found.
+ virtual DeclTy *isTemplateName(IdentifierInfo &II, Scope *S,
+ const CXXScopeSpec *SS = 0);
+
/// ActOnDeclarator - If this is a typedef declarator, we modify the
/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
/// popped.
Modified: cfe/trunk/include/clang/Parse/Ownership.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Ownership.h?rev=61208&r1=61207&r2=61208&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Ownership.h (original)
+++ cfe/trunk/include/clang/Parse/Ownership.h Thu Dec 18 13:37:40 2008
@@ -30,6 +30,7 @@
// what types are required to be identical for the actions.
typedef void ExprTy;
typedef void StmtTy;
+ typedef void TemplateArgTy;
/// ActionResult - This structure is used while parsing/acting on
/// expressions, stmts, etc. It encapsulates both the object returned by
@@ -57,6 +58,7 @@
/// pointers need access to them.
virtual void DeleteExpr(ExprTy *E) {}
virtual void DeleteStmt(StmtTy *E) {}
+ virtual void DeleteTemplateArg(TemplateArgTy *E) {}
};
/// ASTDestroyer - The type of an AST node destruction function pointer.
@@ -71,6 +73,9 @@
template <> struct DestroyerToUID<&ActionBase::DeleteStmt> {
static const unsigned UID = 1;
};
+ template <> struct DestroyerToUID<&ActionBase::DeleteTemplateArg> {
+ static const unsigned UID = 1;
+ };
/// ASTOwningResult - A moveable smart pointer for AST nodes that also
/// has an extra flag to indicate an additional success status.
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=61208&r1=61207&r2=61208&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Dec 18 13:37:40 2008
@@ -78,14 +78,16 @@
typedef Action::BaseTy BaseTy;
typedef Action::MemInitTy MemInitTy;
typedef Action::CXXScopeTy CXXScopeTy;
+ typedef Action::TemplateArgTy TemplateArgTy;
- typedef Action::ExprResult ExprResult;
- typedef Action::StmtResult StmtResult;
- typedef Action::BaseResult BaseResult;
- typedef Action::MemInitResult MemInitResult;
+ typedef Action::ExprResult ExprResult;
+ typedef Action::StmtResult StmtResult;
+ typedef Action::BaseResult BaseResult;
+ typedef Action::MemInitResult MemInitResult;
typedef Action::OwningExprResult OwningExprResult;
typedef Action::OwningStmtResult OwningStmtResult;
+ typedef Action::OwningTemplateArgResult OwningTemplateArgResult;
typedef Action::ExprArg ExprArg;
@@ -100,8 +102,15 @@
OwningExprResult ExprError() { return OwningExprResult(Actions, true); }
OwningStmtResult StmtError() { return OwningStmtResult(Actions, true); }
+ OwningTemplateArgResult TemplateArgError() {
+ return OwningTemplateArgResult(Actions, true);
+ }
+
OwningExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); }
OwningStmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); }
+ OwningTemplateArgResult TemplateArgError(const DiagnosticBuilder &) {
+ return TemplateArgError();
+ }
// Parsing methods.
@@ -936,6 +945,12 @@
DeclTy *ParseTypeParameter();
DeclTy *ParseTemplateTemplateParameter();
DeclTy *ParseNonTypeTemplateParameter();
+ // C++ 14.3: Template arguments [temp.arg]
+ typedef llvm::SmallVector<TemplateArgTy*, 8> TemplateArgList;
+ void AnnotateTemplateIdToken(DeclTy *Template, const CXXScopeSpec *SS = 0);
+ bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
+ OwningTemplateArgResult ParseTemplateArgument();
+
};
} // end namespace clang
Modified: cfe/trunk/lib/Parse/MinimalAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/MinimalAction.cpp?rev=61208&r1=61207&r2=61208&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/MinimalAction.cpp (original)
+++ cfe/trunk/lib/Parse/MinimalAction.cpp Thu Dec 18 13:37:40 2008
@@ -73,6 +73,16 @@
return false;
}
+ /// isTemplateName - Determines whether the identifier II is a
+ /// template name in the current scope, and returns the template
+ /// declaration if II names a template. An optional CXXScope can be
+ /// passed to indicate the C++ scope in which the identifier will be
+ /// found.
+Action::DeclTy *MinimalAction::isTemplateName(IdentifierInfo &II, Scope *S,
+ const CXXScopeSpec *SS ) {
+ return 0;
+}
+
/// ActOnDeclarator - If this is a typedef declarator, we modify the
/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
/// popped.
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=61208&r1=61207&r2=61208&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Dec 18 13:37:40 2008
@@ -1452,13 +1452,27 @@
if (Tok.is(tok::identifier)) {
assert(Tok.getIdentifierInfo() && "Not an identifier?");
- // Determine whether this identifier is a C++ constructor name or
- // a normal identifier.
- if (Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope)) {
+
+ // If this identifier is followed by a '<', we may have a template-id.
+ DeclTy *Template;
+ if (getLang().CPlusPlus && NextToken().is(tok::less) &&
+ (Template = Actions.isTemplateName(*Tok.getIdentifierInfo(),
+ CurScope))) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ AnnotateTemplateIdToken(Template, 0);
+ // FIXME: Set the declarator to a template-id. How? I don't
+ // know... for now, just use the identifier.
+ D.SetIdentifier(II, Tok.getLocation());
+ }
+ // If this identifier is the name of the current class, it's a
+ // constructor name.
+ else if (getLang().CPlusPlus &&
+ Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope))
D.setConstructor(Actions.isTypeName(*Tok.getIdentifierInfo(),
CurScope),
Tok.getLocation());
- } else
+ // This is a normal identifier.
+ else
D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken();
goto PastIdentifier;
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=61208&r1=61207&r2=61208&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Thu Dec 18 13:37:40 2008
@@ -46,8 +46,19 @@
// Try to parse the template parameters, and the declaration if
// successful.
DeclTy *TemplateDecl = 0;
- if(ParseTemplateParameters(0))
+ if (Tok.is(tok::less) && NextToken().is(tok::greater)) {
+ // This is a template specialization. Just consume the angle
+ // brackets and parse the declaration or function definition that
+ // follows.
+ // FIXME: Record somehow that we're in an explicit specialization.
+ ConsumeToken();
+ ConsumeToken();
+ TemplateParmScope.Exit();
TemplateDecl = ParseDeclarationOrFunctionDefinition();
+ } else {
+ if(ParseTemplateParameters(0))
+ TemplateDecl = ParseDeclarationOrFunctionDefinition();
+ }
return TemplateDecl;
}
@@ -243,7 +254,7 @@
/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
/// template parameters (e.g., in "template<int Size> class array;").
-
+///
/// template-parameter:
/// ...
/// parameter-declaration
@@ -289,3 +300,96 @@
return Param;
}
+
+/// AnnotateTemplateIdToken - The current token is an identifier that
+/// refers to the template declaration Template, and is followed by a
+/// '<'. Turn this template-id into a template-id annotation token.
+void Parser::AnnotateTemplateIdToken(DeclTy *Template, const CXXScopeSpec *SS) {
+ assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
+ assert(Template && Tok.is(tok::identifier) && NextToken().is(tok::less) &&
+ "Parser isn't at the beginning of a template-id");
+
+ // Consume the template-name.
+ SourceLocation TemplateNameLoc = ConsumeToken();
+
+ // Consume the '<'.
+ SourceLocation LAngleLoc = ConsumeToken();
+
+ // Parse the optional template-argument-list.
+ TemplateArgList TemplateArgs;
+ if (Tok.isNot(tok::greater) && ParseTemplateArgumentList(TemplateArgs)) {
+ // Try to find the closing '>'.
+ SkipUntil(tok::greater, true, true);
+
+ // FIXME: What's our recovery strategy for failed template-argument-lists?
+ return;
+ }
+
+ if (Tok.isNot(tok::greater))
+ return;
+
+ // Determine the location of the '>'. We won't actually consume this
+ // token, because we'll be replacing it with the template-id.
+ SourceLocation RAngleLoc = Tok.getLocation();
+
+ Tok.setKind(tok::annot_template_id);
+ Tok.setAnnotationEndLoc(RAngleLoc);
+ Tok.setLocation(TemplateNameLoc);
+ if (SS && SS->isNotEmpty())
+ Tok.setLocation(SS->getBeginLoc());
+
+ TemplateIdAnnotation *TemplateId
+ = (TemplateIdAnnotation *)malloc(sizeof(TemplateIdAnnotation) +
+ sizeof(TemplateArgTy*) * TemplateArgs.size());
+ TemplateId->TemplateNameLoc = TemplateNameLoc;
+ TemplateId->Template = Template;
+ TemplateId->LAngleLoc = LAngleLoc;
+ TemplateId->NumArgs = TemplateArgs.size();
+ TemplateArgTy **Args = (TemplateArgTy**)(TemplateId + 1);
+ for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
+ Args[Arg] = TemplateArgs[Arg];
+ Tok.setAnnotationValue(TemplateId);
+
+ // In case the tokens were cached, have Preprocessor replace them with the
+ // annotation token.
+ PP.AnnotateCachedTokens(Tok);
+}
+
+/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
+///
+/// template-argument: [C++ 14.2]
+/// assignment-expression
+/// type-id
+/// id-expression
+Parser::OwningTemplateArgResult Parser::ParseTemplateArgument() {
+ // FIXME: Implement this!
+ return TemplateArgError();
+}
+
+/// ParseTemplateArgumentList - Parse a C++ template-argument-list
+/// (C++ [temp.names]). Returns true if there was an error.
+///
+/// template-argument-list: [C++ 14.2]
+/// template-argument
+/// template-argument-list ',' template-argument
+bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
+ while (true) {
+ OwningTemplateArgResult Arg = ParseTemplateArgument();
+ if (Arg.isInvalid()) {
+ SkipUntil(tok::comma, tok::greater, true, true);
+ return true;
+ }
+ else
+ TemplateArgs.push_back(Arg.release());
+
+ // If the next token is a comma, consume it and keep reading
+ // arguments.
+ if (Tok.isNot(tok::comma)) break;
+
+ // Consume the comma.
+ ConsumeToken();
+ }
+
+ return Tok.isNot(tok::greater);
+}
+
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=61208&r1=61207&r2=61208&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Thu Dec 18 13:37:40 2008
@@ -722,6 +722,7 @@
/// specifier, and another one to get the actual type inside
/// ParseDeclarationSpecifiers).
void Parser::TryAnnotateTypeOrScopeToken() {
+ // FIXME: what about template-ids?
if (Tok.is(tok::annot_qualtypename) || Tok.is(tok::annot_cxxscope))
return;
@@ -730,23 +731,39 @@
MaybeParseCXXScopeSpecifier(SS);
if (Tok.is(tok::identifier)) {
- TypeTy *Ty = Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope, &SS);
- if (Ty) {
- // This is a typename. Replace the current token in-place with an
- // annotation type token.
- Tok.setKind(tok::annot_qualtypename);
- Tok.setAnnotationValue(Ty);
- Tok.setAnnotationEndLoc(Tok.getLocation());
- if (SS.isNotEmpty()) // it was a C++ qualified type name.
- Tok.setLocation(SS.getBeginLoc());
-
- // In case the tokens were cached, have Preprocessor replace them with the
- // annotation token.
- PP.AnnotateCachedTokens(Tok);
- return;
+ DeclTy *Template = 0;
+ // If this is a template-id, annotate the template-id token.
+ if (getLang().CPlusPlus && NextToken().is(tok::less) &&
+ (Template = Actions.isTemplateName(*Tok.getIdentifierInfo(), CurScope,
+ &SS)))
+ AnnotateTemplateIdToken(Template, &SS);
+ else {
+ // Determine whether the identifier is a type name.
+ TypeTy *Ty = Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope, &SS);
+ if (Ty) {
+ // This is a typename. Replace the current token in-place with an
+ // annotation type token.
+ Tok.setKind(tok::annot_qualtypename);
+ Tok.setAnnotationValue(Ty);
+ Tok.setAnnotationEndLoc(Tok.getLocation());
+ if (SS.isNotEmpty()) // it was a C++ qualified type name.
+ Tok.setLocation(SS.getBeginLoc());
+
+ // In case the tokens were cached, have Preprocessor replace
+ // them with the annotation token.
+ PP.AnnotateCachedTokens(Tok);
+ return;
+ }
}
+
+ // We either have an identifier that is not a type name or we have
+ // just created a template-id that might be a type name. Both
+ // cases will be handled below.
}
+ // FIXME: check for a template-id token here, and look it up if it
+ // names a type.
+
if (SS.isNotEmpty()) {
// A C++ scope specifier that isn't followed by a typename.
// Push the current token back into the token stream (or revert it if it is
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=61208&r1=61207&r2=61208&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Dec 18 13:37:40 2008
@@ -1005,6 +1005,8 @@
//===--------------------------------------------------------------------===//
// C++ Templates [C++ 14]
//
+ virtual DeclTy *isTemplateName(IdentifierInfo &II, Scope *S,
+ const CXXScopeSpec *SS = 0);
bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename,
SourceLocation KeyLoc,
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=61208&r1=61207&r2=61208&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Dec 18 13:37:40 2008
@@ -18,6 +18,42 @@
using namespace clang;
+/// isTemplateName - Determines whether the identifier II is a
+/// template name in the current scope, and returns the template
+/// declaration if II names a template. An optional CXXScope can be
+/// passed to indicate the C++ scope in which the identifier will be
+/// found.
+Sema::DeclTy *Sema::isTemplateName(IdentifierInfo &II, Scope *S,
+ const CXXScopeSpec *SS) {
+ DeclContext *DC = 0;
+ if (SS) {
+ if (SS->isInvalid())
+ return 0;
+ DC = static_cast<DeclContext*>(SS->getScopeRep());
+ }
+ Decl *IIDecl = LookupDecl(&II, Decl::IDNS_Ordinary, S, DC, false);
+
+ if (IIDecl) {
+ // FIXME: We need to represent templates via some kind of
+ // TemplateDecl, because what follows is a hack that only works in
+ // one specific case.
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(IIDecl)) {
+ if (FD->getType()->isDependentType())
+ return FD;
+ } else if (OverloadedFunctionDecl *Ovl
+ = dyn_cast<OverloadedFunctionDecl>(IIDecl)) {
+ for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
+ FEnd = Ovl->function_end();
+ F != FEnd; ++F) {
+ if ((*F)->getType()->isDependentType())
+ return Ovl;
+ }
+ }
+ return 0;
+ }
+ return 0;
+}
+
/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
/// that the template parameter 'PrevDecl' is being shadowed by a new
/// declaration at location Loc. Returns true to indicate that this is
Added: cfe/trunk/test/SemaCXX/template-specialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/template-specialization.cpp?rev=61208&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/template-specialization.cpp (added)
+++ cfe/trunk/test/SemaCXX/template-specialization.cpp Thu Dec 18 13:37:40 2008
@@ -0,0 +1,4 @@
+// RUN: clang -fsyntax-only -verify %s
+template<int N> void f(int (&array)[N]);
+
+template<> void f<1>(int (&array)[1]) { }
Modified: cfe/trunk/test/SemaObjCXX/overload.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/overload.mm?rev=61208&r1=61207&r2=61208&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/overload.mm (original)
+++ cfe/trunk/test/SemaObjCXX/overload.mm Thu Dec 18 13:37:40 2008
@@ -1,4 +1,4 @@
-// RUN clang -fsyntax-only -verify %s
+// RUN: clang -fsyntax-only -verify %s
@protocol P0
@end
More information about the cfe-commits
mailing list