[cfe-commits] r85966 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Lex/Token.h include/clang/Parse/Action.h include/clang/Parse/DeclSpec.h lib/Parse/MinimalAction.cpp lib/Parse/ParseExprCXX.cpp lib/Parse/Parser.cpp lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/TreeTransform.h test/SemaTemplate/operator-function-id-template.cpp

Douglas Gregor dgregor at apple.com
Tue Nov 3 15:16:33 PST 2009


Author: dgregor
Date: Tue Nov  3 17:16:33 2009
New Revision: 85966

URL: http://llvm.org/viewvc/llvm-project?rev=85966&view=rev
Log:
Parsing and semantic analysis for template-ids that name overloaded
operators, e.g., 

  operator+<int>

which now works in declarators, id-expressions, and member access
expressions. This commit only implements the non-dependent case, where
we can resolve the template-id to an actual declaration.

Added:
    cfe/trunk/test/SemaTemplate/operator-function-id-template.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Lex/Token.h
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/DeclSpec.h
    cfe/trunk/lib/Parse/MinimalAction.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/TreeTransform.h

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=85966&r1=85965&r2=85966&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue Nov  3 17:16:33 2009
@@ -295,8 +295,6 @@
 // C++ declarations
 def err_friend_decl_defines_class : Error<
   "cannot define a type in a friend declaration">;
-def warn_operator_template_id_ignores_args : Error<
-  "clang bug: ignoring template arguments provided for operator">;
   
 // Language specific pragmas
 // - Generic warnings

Modified: cfe/trunk/include/clang/Lex/Token.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Token.h?rev=85966&r1=85965&r2=85966&view=diff

==============================================================================
--- cfe/trunk/include/clang/Lex/Token.h (original)
+++ cfe/trunk/include/clang/Lex/Token.h Tue Nov  3 17:16:33 2009
@@ -17,6 +17,7 @@
 #include "clang/Basic/TemplateKinds.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/OperatorKinds.h"
 #include <cstdlib>
 
 namespace clang {
@@ -261,6 +262,9 @@
   /// FIXME: Temporarily stores the name of a specialization
   IdentifierInfo *Name;
 
+  /// FIXME: Temporarily stores the overloaded operator kind.
+  OverloadedOperatorKind Operator;
+  
   /// The declaration of the template corresponding to the
   /// template-name. This is an Action::DeclTy*.
   void *Template;

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=85966&r1=85965&r2=85966&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Nov  3 17:16:33 2009
@@ -236,30 +236,36 @@
   virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
                                   const CXXScopeSpec *SS = 0) = 0;
 
-  /// \brief Determine whether the given identifier refers to the name of a
+  /// \brief Determine whether the given name refers to a template.
+  ///
+  /// This callback is used by the parser after it has seen a '<' to determine
+  /// whether the given name refers to a template and, if so, what kind of 
   /// template.
   ///
-  /// \param S the scope in which name lookup occurs
+  /// \param S the scope in which the name occurs.
   ///
-  /// \param II the identifier that we are querying to determine whether it
-  /// is a template.
+  /// \param SS the C++ nested-name-specifier that precedes the template name,
+  /// if any.
   ///
-  /// \param IdLoc the source location of the identifier
+  /// \param Name the name that we are querying to determine whether it is
+  /// a template.
   ///
-  /// \param SS the C++ scope specifier that precedes the template name, if
-  /// any.
+  /// \param ObjectType if we are determining whether the given name is a 
+  /// template name in the context of a member access expression (e.g., 
+  /// \c p->X<int>), this is the type of the object referred to by the
+  /// member access (e.g., \c p).
   ///
   /// \param EnteringContext whether we are potentially entering the context
-  /// referred to by the scope specifier \p SS
+  /// referred to by the nested-name-specifier \p SS, which allows semantic
+  /// analysis to look into uninstantiated templates.
   ///
   /// \param Template if the name does refer to a template, the declaration
   /// of the template that the name refers to.
   ///
   /// \returns the kind of template that this name refers to.
   virtual TemplateNameKind isTemplateName(Scope *S,
-                                          const IdentifierInfo &II,
-                                          SourceLocation IdLoc,
-                                          const CXXScopeSpec *SS,
+                                          const CXXScopeSpec &SS,
+                                          UnqualifiedId &Name,
                                           TypeTy *ObjectType,
                                           bool EnteringContext,
                                           TemplateTy &Template) = 0;
@@ -1616,22 +1622,19 @@
   ///
   /// \param TemplateKWLoc the location of the "template" keyword (if any).
   ///
-  /// \param Name the name of the template (an identifier)
-  ///
-  /// \param NameLoc the location of the identifier
-  ///
   /// \param SS the nested-name-specifier that precedes the "template" keyword
-  /// or the template name. FIXME: If the dependent template name occurs in
+  /// or the template name. If the dependent template name occurs in
   /// a member access expression, e.g., "x.template f<T>", this
   /// nested-name-specifier will be empty.
   ///
+  /// \param Name the name of the template.
+  ///
   /// \param ObjectType if this dependent template name occurs in the
   /// context of a member access expression, the type of the object being
   /// accessed.
   virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
-                                                const IdentifierInfo &Name,
-                                                SourceLocation NameLoc,
                                                 const CXXScopeSpec &SS,
+                                                UnqualifiedId &Name,
                                                 TypeTy *ObjectType) {
     return TemplateTy();
   }
@@ -2333,13 +2336,12 @@
                                   const CXXScopeSpec *SS);
 
   virtual TemplateNameKind isTemplateName(Scope *S,
-                                          const IdentifierInfo &II,
-                                          SourceLocation IdLoc,
-                                          const CXXScopeSpec *SS,
+                                          const CXXScopeSpec &SS,
+                                          UnqualifiedId &Name,
                                           TypeTy *ObjectType,
                                           bool EnteringContext,
                                           TemplateTy &Template);
-
+  
   /// 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/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=85966&r1=85965&r2=85966&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Tue Nov  3 17:16:33 2009
@@ -561,9 +561,9 @@
   ///
   /// \param Id the parsed identifier.
   /// \param IdLoc the location of the parsed identifier.
-  void setIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) {
+  void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) {
     Kind = IK_Identifier;
-    Identifier = Id;
+    Identifier = const_cast<IdentifierInfo *>(Id);
     StartLocation = EndLocation = IdLoc;
   }
   

Modified: cfe/trunk/lib/Parse/MinimalAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/MinimalAction.cpp?rev=85966&r1=85965&r2=85966&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/MinimalAction.cpp (original)
+++ cfe/trunk/lib/Parse/MinimalAction.cpp Tue Nov  3 17:16:33 2009
@@ -161,9 +161,8 @@
 
 TemplateNameKind
 MinimalAction::isTemplateName(Scope *S,
-                              const IdentifierInfo &II,
-                              SourceLocation IdLoc,
-                              const CXXScopeSpec *SS,
+                              const CXXScopeSpec &SS,
+                              UnqualifiedId &Name,
                               TypeTy *ObjectType,
                               bool EnteringScope,
                               TemplateTy &TemplateDecl) {

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=85966&r1=85965&r2=85966&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Tue Nov  3 17:16:33 2009
@@ -125,10 +125,10 @@
         break;
       }
 
+      UnqualifiedId TemplateName;
+      TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
       TemplateTy Template
-        = Actions.ActOnDependentTemplateName(TemplateKWLoc,
-                                             *Tok.getIdentifierInfo(),
-                                             Tok.getLocation(), SS,
+        = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
                                              ObjectType);
       if (!Template)
         break;
@@ -220,9 +220,10 @@
     //   type-name '<'
     if (Next.is(tok::less)) {
       TemplateTy Template;
-      if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, II,
-                                                        Tok.getLocation(),
-                                                        &SS,
+      UnqualifiedId TemplateName;
+      TemplateName.setIdentifier(&II, Tok.getLocation());
+      if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, 
+                                                        TemplateName,
                                                         ObjectType,
                                                         EnteringContext,
                                                         Template)) {
@@ -741,45 +742,30 @@
   TemplateNameKind TNK = TNK_Non_template;
   switch (Id.getKind()) {
   case UnqualifiedId::IK_Identifier:
-    TNK = Actions.isTemplateName(CurScope, *Id.Identifier, Id.StartLocation, 
-                                 &SS, ObjectType, EnteringContext, Template);
+  case UnqualifiedId::IK_OperatorFunctionId:
+    TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType, EnteringContext, 
+                                 Template);
     break;
       
-  case UnqualifiedId::IK_OperatorFunctionId: {
-    // FIXME: Temporary hack: warn that we are completely ignoring the 
-    // template arguments for now.
-    // Parse the enclosed template argument list and throw it away.
-    SourceLocation LAngleLoc, RAngleLoc;
-    TemplateArgList TemplateArgs;
-    TemplateArgIsTypeList TemplateArgIsType;
-    TemplateArgLocationList TemplateArgLocations;
-    if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
-                                         &SS, true, LAngleLoc,
-                                         TemplateArgs,
-                                         TemplateArgIsType,
-                                         TemplateArgLocations,
-                                         RAngleLoc))
-      return true;
-    
-    Diag(Id.StartLocation, diag::warn_operator_template_id_ignores_args)
-      << SourceRange(LAngleLoc, RAngleLoc);
-    break;
-  }
-      
-  case UnqualifiedId::IK_ConstructorName:
-    TNK = Actions.isTemplateName(CurScope, *Name, NameLoc, &SS, ObjectType, 
+  case UnqualifiedId::IK_ConstructorName: {
+    UnqualifiedId TemplateName;
+    TemplateName.setIdentifier(Name, NameLoc);
+    TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType, 
                                  EnteringContext, Template);
     break;
+  }
       
-  case UnqualifiedId::IK_DestructorName:
+  case UnqualifiedId::IK_DestructorName: {
+    UnqualifiedId TemplateName;
+    TemplateName.setIdentifier(Name, NameLoc);
     if (ObjectType) {
-      Template = Actions.ActOnDependentTemplateName(SourceLocation(), *Name, 
-                                                    NameLoc, SS, ObjectType);
+      Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS, 
+                                                    TemplateName, ObjectType);
       TNK = TNK_Dependent_template_name;
       if (!Template.get())
         return true;
     } else {
-      TNK = Actions.isTemplateName(CurScope, *Name, NameLoc, &SS, ObjectType, 
+      TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType, 
                                    EnteringContext, Template);
       
       if (TNK == TNK_Non_template && Id.DestructorName == 0) {
@@ -794,6 +780,7 @@
       }
     }
     break;
+  }
       
   default:
     return false;
@@ -824,9 +811,12 @@
 
     if (Id.getKind() == UnqualifiedId::IK_Identifier) {
       TemplateId->Name = Id.Identifier;
+      TemplateId->Operator = OO_None;
       TemplateId->TemplateNameLoc = Id.StartLocation;
     } else {
-      // FIXME: Handle IK_OperatorFunctionId
+      TemplateId->Name = 0;
+      TemplateId->Operator = Id.OperatorFunctionId.Operator;
+      TemplateId->TemplateNameLoc = Id.StartLocation;
     }
 
     TemplateId->Template = Template.getAs<void*>();

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=85966&r1=85965&r2=85966&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Nov  3 17:16:33 2009
@@ -935,9 +935,10 @@
     // If this is a template-id, annotate with a template-id or type token.
     if (NextToken().is(tok::less)) {
       TemplateTy Template;
+      UnqualifiedId TemplateName;
+      TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
       if (TemplateNameKind TNK
-            = Actions.isTemplateName(CurScope, *Tok.getIdentifierInfo(),
-                                     Tok.getLocation(), &SS,
+            = Actions.isTemplateName(CurScope, SS, TemplateName, 
                                      /*ObjectType=*/0, EnteringContext,
                                      Template))
         if (AnnotateTemplateIdToken(Template, TNK, &SS)) {

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=85966&r1=85965&r2=85966&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Nov  3 17:16:33 2009
@@ -2397,9 +2397,8 @@
   // C++ Templates [C++ 14]
   //
   virtual TemplateNameKind isTemplateName(Scope *S,
-                                          const IdentifierInfo &II,
-                                          SourceLocation IdLoc,
-                                          const CXXScopeSpec *SS,
+                                          const CXXScopeSpec &SS,
+                                          UnqualifiedId &Name,
                                           TypeTy *ObjectType,
                                           bool EnteringContext,
                                           TemplateTy &Template);
@@ -2499,9 +2498,8 @@
                                        SourceLocation RAngleLoc);
 
   virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
-                                                const IdentifierInfo &Name,
-                                                SourceLocation NameLoc,
                                                 const CXXScopeSpec &SS,
+                                                UnqualifiedId &Name,
                                                 TypeTy *ObjectType);
 
   bool CheckClassTemplatePartialSpecializationArgs(

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=85966&r1=85965&r2=85966&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Nov  3 17:16:33 2009
@@ -98,29 +98,43 @@
 }
 
 TemplateNameKind Sema::isTemplateName(Scope *S,
-                                      const IdentifierInfo &II,
-                                      SourceLocation IdLoc,
-                                      const CXXScopeSpec *SS,
+                                      const CXXScopeSpec &SS,
+                                      UnqualifiedId &Name,
                                       TypeTy *ObjectTypePtr,
                                       bool EnteringContext,
                                       TemplateTy &TemplateResult) {
+  DeclarationName TName;
+  
+  switch (Name.getKind()) {
+  case UnqualifiedId::IK_Identifier:
+    TName = DeclarationName(Name.Identifier);
+    break;
+      
+  case UnqualifiedId::IK_OperatorFunctionId:
+    TName = Context.DeclarationNames.getCXXOperatorName(
+                                              Name.OperatorFunctionId.Operator);
+    break;
+
+  default:
+    return TNK_Non_template;
+  }
+  
   // Determine where to perform name lookup
   DeclContext *LookupCtx = 0;
   bool isDependent = false;
   if (ObjectTypePtr) {
     // This nested-name-specifier occurs in a member access expression, e.g.,
     // x->B::f, and we are looking into the type of the object.
-    assert((!SS || !SS->isSet()) &&
-           "ObjectType and scope specifier cannot coexist");
+    assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
     QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
     LookupCtx = computeDeclContext(ObjectType);
     isDependent = ObjectType->isDependentType();
-  } else if (SS && SS->isSet()) {
+  } else if (SS.isSet()) {
     // This nested-name-specifier occurs after another nested-name-specifier,
     // so long into the context associated with the prior nested-name-specifier.
 
-    LookupCtx = computeDeclContext(*SS, EnteringContext);
-    isDependent = isDependentScopeSpecifier(*SS);
+    LookupCtx = computeDeclContext(SS, EnteringContext);
+    isDependent = isDependentScopeSpecifier(SS);
   }
 
   LookupResult Found;
@@ -132,10 +146,10 @@
     // nested-name-specifier.
 
     // The declaration context must be complete.
-    if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS))
+    if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS))
       return TNK_Non_template;
 
-    LookupQualifiedName(Found, LookupCtx, &II, LookupOrdinaryName);
+    LookupQualifiedName(Found, LookupCtx, TName, LookupOrdinaryName);
 
     if (ObjectTypePtr && Found.getKind() == LookupResult::NotFound) {
       // C++ [basic.lookup.classref]p1:
@@ -150,7 +164,7 @@
       //
       // FIXME: When we're instantiating a template, do we actually have to
       // look in the scope of the template? Seems fishy...
-      LookupName(Found, S, &II, LookupOrdinaryName);
+      LookupName(Found, S, TName, LookupOrdinaryName);
       ObjectTypeSearchedInScope = true;
     }
   } else if (isDependent) {
@@ -158,7 +172,7 @@
     return TNK_Non_template;
   } else {
     // Perform unqualified name lookup in the current scope.
-    LookupName(Found, S, &II, LookupOrdinaryName);
+    LookupName(Found, S, TName, LookupOrdinaryName);
   }
 
   // FIXME: Cope with ambiguous name-lookup results.
@@ -177,7 +191,7 @@
     //   postfix-expression and [...]
     //
     LookupResult FoundOuter;
-    LookupName(FoundOuter, S, &II, LookupOrdinaryName);
+    LookupName(FoundOuter, S, TName, LookupOrdinaryName);
     // FIXME: Handle ambiguities in this lookup better
     NamedDecl *OuterTemplate
       = isAcceptableTemplateName(Context, FoundOuter.getAsSingleDecl(Context));
@@ -194,8 +208,10 @@
       //     entity as the one found in the class of the object expression,
       //     otherwise the program is ill-formed.
       if (OuterTemplate->getCanonicalDecl() != Template->getCanonicalDecl()) {
-        Diag(IdLoc, diag::err_nested_name_member_ref_lookup_ambiguous)
-          << &II;
+        Diag(Name.getSourceRange().getBegin(), 
+             diag::err_nested_name_member_ref_lookup_ambiguous)
+          << TName
+          << Name.getSourceRange();
         Diag(Template->getLocation(), diag::note_ambig_member_ref_object_type)
           << QualType::getFromOpaquePtr(ObjectTypePtr);
         Diag(OuterTemplate->getLocation(), diag::note_ambig_member_ref_scope);
@@ -206,9 +222,9 @@
     }
   }
 
-  if (SS && SS->isSet() && !SS->isInvalid()) {
+  if (SS.isSet() && !SS.isInvalid()) {
     NestedNameSpecifier *Qualifier
-      = static_cast<NestedNameSpecifier *>(SS->getScopeRep());
+      = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
     if (OverloadedFunctionDecl *Ovl
           = dyn_cast<OverloadedFunctionDecl>(Template))
       TemplateResult
@@ -1345,9 +1361,8 @@
 /// of the "template" keyword, and "apply" is the \p Name.
 Sema::TemplateTy
 Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
-                                 const IdentifierInfo &Name,
-                                 SourceLocation NameLoc,
                                  const CXXScopeSpec &SS,
+                                 UnqualifiedId &Name,
                                  TypeTy *ObjectType) {
   if ((ObjectType &&
        computeDeclContext(QualType::getFromOpaquePtr(ObjectType))) ||
@@ -1369,11 +1384,13 @@
     // "template" keyword is now permitted). We follow the C++0x
     // rules, even in C++03 mode, retroactively applying the DR.
     TemplateTy Template;
-    TemplateNameKind TNK = isTemplateName(0, Name, NameLoc, &SS, ObjectType,
+    TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType,
                                           false, Template);
     if (TNK == TNK_Non_template) {
-      Diag(NameLoc, diag::err_template_kw_refers_to_non_template)
-        << &Name;
+      Diag(Name.getSourceRange().getBegin(), 
+           diag::err_template_kw_refers_to_non_template)
+        << GetNameFromUnqualifiedId(Name)
+        << Name.getSourceRange();
       return TemplateTy();
     }
 
@@ -1382,7 +1399,21 @@
 
   NestedNameSpecifier *Qualifier
     = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
-  return TemplateTy::make(Context.getDependentTemplateName(Qualifier, &Name));
+  
+  switch (Name.getKind()) {
+  case UnqualifiedId::IK_Identifier:
+    return TemplateTy::make(Context.getDependentTemplateName(Qualifier, 
+                                                             Name.Identifier));
+    
+  default:
+    break;
+  }
+  
+  Diag(Name.getSourceRange().getBegin(), 
+       diag::err_template_kw_refers_to_non_template)
+    << GetNameFromUnqualifiedId(Name)
+    << Name.getSourceRange();
+  return TemplateTy();
 }
 
 bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=85966&r1=85965&r2=85966&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Nov  3 17:16:33 2009
@@ -5184,11 +5184,12 @@
   CXXScopeSpec SS;
   SS.setRange(SourceRange(getDerived().getBaseLocation()));
   SS.setScopeRep(Qualifier);
+  UnqualifiedId Name;
+  Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation());
   return getSema().ActOnDependentTemplateName(
                                       /*FIXME:*/getDerived().getBaseLocation(),
-                                              II,
-                                      /*FIXME:*/getDerived().getBaseLocation(),
                                               SS,
+                                              Name,
                                               ObjectType.getAsOpaquePtr())
            .template getAsVal<TemplateName>();
 }

Added: cfe/trunk/test/SemaTemplate/operator-function-id-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/operator-function-id-template.cpp?rev=85966&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/operator-function-id-template.cpp (added)
+++ cfe/trunk/test/SemaTemplate/operator-function-id-template.cpp Tue Nov  3 17:16:33 2009
@@ -0,0 +1,27 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+struct A { 
+  template<typename U> A<T> operator+(U);
+};
+
+template<int Value, typename T> bool operator==(A<T>, A<T>);
+
+template<> bool operator==<0>(A<int>, A<int>);
+
+bool test_qualified_id(A<int> ai) {
+  return ::operator==<0, int>(ai, ai);
+}
+
+void test_op(A<int> a, int i) {
+  const A<int> &air = a.operator+<int>(i);
+}
+
+template<typename T>
+void test_op_template(A<T> at, T x) {
+  // FIXME: Not yet implemented.
+  //  const A<T> &atr = at.template operator+<T>(x);
+  //  const A<T> &atr2 = at.A<T>::template operator+<T>(x);
+}
+
+template void test_op_template<float>(A<float>, float);





More information about the cfe-commits mailing list