[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