[cfe-commits] r82806 - in /cfe/trunk: include/clang/Parse/DeclSpec.h lib/Parse/ParseDecl.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaType.cpp test/SemaTemplate/explicit-instantiation.cpp

Douglas Gregor dgregor at apple.com
Fri Sep 25 14:45:24 PDT 2009


Author: dgregor
Date: Fri Sep 25 16:45:23 2009
New Revision: 82806

URL: http://llvm.org/viewvc/llvm-project?rev=82806&view=rev
Log:
Declarators can now properly represent template-ids, e.g., for

  template void f<int>(int);
                ~~~~~~
Previously, we silently dropped the template arguments. With this
change, we now use the template arguments (when available) as the
explicitly-specified template arguments used to aid template argument
deduction for explicit template instantiations.


Modified:
    cfe/trunk/include/clang/Parse/DeclSpec.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Fri Sep 25 16:45:23 2009
@@ -794,8 +794,10 @@
     DK_Constructor,      // A C++ constructor (identifier is the class name)
     DK_Destructor,       // A C++ destructor  (identifier is ~class name)
     DK_Operator,         // A C++ overloaded operator name
-    DK_Conversion        // A C++ conversion function (identifier is
+    DK_Conversion,       // A C++ conversion function (identifier is
                          // "operator " then the type name)
+    DK_TemplateId        // A C++ template-id naming a function template
+                         // specialization.
   };
 
 private:
@@ -839,6 +841,10 @@
     /// When Kind is DK_Operator, this is the actual overloaded
     /// operator that this declarator names.
     OverloadedOperatorKind OperatorKind;
+    
+    /// When Kind is DK_TemplateId, this is the template-id annotation that
+    /// contains the template and its template arguments.
+    TemplateIdAnnotation *TemplateId;
   };
 
   /// InlineParams - This is a local array used for the first function decl
@@ -916,6 +922,10 @@
     Identifier = 0;
     IdentifierLoc = SourceLocation();
     Range = DS.getSourceRange();
+    
+    if (Kind == DK_TemplateId)
+      TemplateId->Destroy();
+    
     Kind = DK_Abstract;
 
     for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i)
@@ -1023,6 +1033,16 @@
       SetRangeEnd(EndLoc);
   }
 
+  /// \brief Set this declaration to be a C++ template-id, which includes the
+  /// template (or set of function templates) along with template arguments.
+  void setTemplateId(TemplateIdAnnotation *TemplateId) {
+    assert(TemplateId && "NULL template-id provided to declarator?");
+    IdentifierLoc = TemplateId->TemplateNameLoc;
+    Kind = DK_TemplateId;
+    SetRangeEnd(TemplateId->RAngleLoc);
+    this->TemplateId = TemplateId;
+  }
+                     
   /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
   /// EndLoc, which should be the last token of the chunk.
   void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) {
@@ -1085,10 +1105,22 @@
   void setExtension(bool Val = true) { Extension = Val; }
   bool getExtension() const { return Extension; }
 
-  ActionBase::TypeTy *getDeclaratorIdType() const { return Type; }
+  ActionBase::TypeTy *getDeclaratorIdType() const { 
+    assert((Kind == DK_Constructor || Kind == DK_Destructor || 
+            Kind == DK_Conversion) && "Declarator kind does not have a type");
+    return Type; 
+  }
 
-  OverloadedOperatorKind getOverloadedOperator() const { return OperatorKind; }
+  OverloadedOperatorKind getOverloadedOperator() const { 
+    assert(Kind == DK_Operator && "Declarator is not an overloaded operator");
+    return OperatorKind; 
+  }
 
+  TemplateIdAnnotation *getTemplateId() { 
+    assert(Kind == DK_TemplateId && "Declarator is not a template-id");
+    return TemplateId;
+  }
+  
   void setInvalidType(bool Val = true) { InvalidType = Val; }
   bool isInvalidType() const {
     return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error;

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Sep 25 16:45:23 2009
@@ -2210,12 +2210,12 @@
 ///
 ///       id-expression: [C++ 5.1]
 ///         unqualified-id
-///         qualified-id            [TODO]
+///         qualified-id
 ///
 ///       unqualified-id: [C++ 5.1]
 ///         identifier
 ///         operator-function-id
-///         conversion-function-id  [TODO]
+///         conversion-function-id
 ///          '~' class-name
 ///         template-id
 ///
@@ -2254,15 +2254,7 @@
         TemplateIdAnnotation *TemplateId
           = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
 
-        // FIXME: Could this template-id name a constructor?
-
-        // FIXME: This is an egregious hack, where we silently ignore
-        // the specialization (which should be a function template
-        // specialization name) and use the name instead. This hack
-        // will go away when we have support for function
-        // specializations.
-        D.SetIdentifier(TemplateId->Name, Tok.getLocation());
-        TemplateId->Destroy();
+        D.setTemplateId(TemplateId);
         ConsumeToken();
         goto PastIdentifier;
       } else if (Tok.is(tok::kw_operator)) {

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Sep 25 16:45:23 2009
@@ -1587,6 +1587,17 @@
     assert(D.getIdentifier() == 0 && "operator names have no identifier");
     return Context.DeclarationNames.getCXXOperatorName(
                                                 D.getOverloadedOperator());
+      
+  case Declarator::DK_TemplateId: {
+    TemplateName Name
+      = TemplateName::getFromVoidPointer(D.getTemplateId()->Template);    
+    if (TemplateDecl *Template = Name.getAsTemplateDecl())
+      return Template->getDeclName();
+    if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl())
+      return Ovl->getDeclName();
+    
+    return DeclarationName();
+  }
   }
 
   assert(false && "Unknown name kind");

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Sep 25 16:45:23 2009
@@ -3409,23 +3409,38 @@
     return DeclPtrTy();
   }
   
+  // Translate the parser's template argument list in our AST format.
+  bool HasExplicitTemplateArgs = false;
+  llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+  if (D.getKind() == Declarator::DK_TemplateId) {
+    TemplateIdAnnotation *TemplateId = D.getTemplateId();
+    ASTTemplateArgsPtr TemplateArgsPtr(*this,
+                                       TemplateId->getTemplateArgs(),
+                                       TemplateId->getTemplateArgIsType(),
+                                       TemplateId->NumArgs);
+    translateTemplateArguments(TemplateArgsPtr,
+                               TemplateId->getTemplateArgLocations(),
+                               TemplateArgs);
+    HasExplicitTemplateArgs = true;
+  }
+  
+  
   // C++ [temp.explicit]p1:
   //   A [...] function [...] can be explicitly instantiated from its template. 
   //   A member function [...] of a class template can be explicitly 
   //  instantiated from the member definition associated with its class 
   //  template.
-  // FIXME: Implement this!
   llvm::SmallVector<FunctionDecl *, 8> Matches;
   for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
        P != PEnd; ++P) {
     NamedDecl *Prev = *P;
-    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
-      // FIXME: If there were any explicitly-specified template arguments, 
-      // don't look for Method declarations.
-      if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
-        Matches.clear();
-        Matches.push_back(Method);
-        break;
+    if (!HasExplicitTemplateArgs) {
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
+        if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
+          Matches.clear();
+          Matches.push_back(Method);
+          break;
+        }
       }
     }
     
@@ -3436,7 +3451,8 @@
     TemplateDeductionInfo Info(Context);
     FunctionDecl *Specialization = 0;
     if (TemplateDeductionResult TDK
-          = DeduceTemplateArguments(FunTmpl, /*FIXME:*/false, 0, 0, 
+          = DeduceTemplateArguments(FunTmpl, HasExplicitTemplateArgs,
+                                    TemplateArgs.data(), TemplateArgs.size(),
                                     R, Specialization, Info)) {
       // FIXME: Keep track of almost-matches?
       (void)TDK;

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Fri Sep 25 16:45:23 2009
@@ -842,7 +842,8 @@
   switch (D.getKind()) {
   case Declarator::DK_Abstract:
   case Declarator::DK_Normal:
-  case Declarator::DK_Operator: {
+  case Declarator::DK_Operator:
+  case Declarator::DK_TemplateId: {
     const DeclSpec &DS = D.getDeclSpec();
     if (OmittedReturnType) {
       // We default to a dependent type initially.  Can be modified by

Modified: cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp?rev=82806&r1=82805&r2=82806&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp (original)
+++ cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp Fri Sep 25 16:45:23 2009
@@ -55,3 +55,17 @@
 template int *X2::f1(int *); // okay
 
 template void X2::f2(int *, int *); // expected-error{{ambiguous}}
+
+
+template<typename T> void print_type();
+
+template void print_type<int>();
+template void print_type<float>();
+
+template<typename T> void print_type(T*);
+
+template void print_type(int*);
+template void print_type<int>(float*); // expected-error{{does not refer}}
+
+void print_type(double*);
+template void print_type<double>(double*);





More information about the cfe-commits mailing list