[cfe-commits] r105882 - in /cfe/trunk: include/clang/AST/Decl.h lib/AST/Decl.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp

Abramo Bagnara abramo.bagnara at gmail.com
Sat Jun 12 01:15:14 PDT 2010


Author: abramo
Date: Sat Jun 12 03:15:14 2010
New Revision: 105882

URL: http://llvm.org/viewvc/llvm-project?rev=105882&view=rev
Log:
Added template parameters info for out-of-line definitions of class template methods.

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=105882&r1=105881&r2=105882&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Sat Jun 12 03:15:14 2010
@@ -28,6 +28,8 @@
 class Stmt;
 class CompoundStmt;
 class StringLiteral;
+class NestedNameSpecifier;
+class TemplateParameterList;
 class TemplateArgumentList;
 class MemberSpecializationInfo;
 class FunctionTemplateSpecializationInfo;
@@ -364,15 +366,42 @@
   static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; }
 };
 
+/// QualifierInfo - A struct with extended info about a syntactic
+/// name qualifier, to be used for the case of out-of-line declarations.
+struct QualifierInfo {
+  /// NNS - The syntactic name qualifier.
+  NestedNameSpecifier *NNS;
+  /// NNSRange - The source range for the qualifier.
+  SourceRange NNSRange;
+  /// NumTemplParamLists - The number of template parameter lists
+  /// that were matched against the template-ids occurring into the NNS.
+  unsigned NumTemplParamLists;
+  /// TemplParamLists - A new-allocated array of size NumTemplParamLists,
+  /// containing pointers to the matched template parameter lists.
+  TemplateParameterList** TemplParamLists;
+
+  /// Default constructor.
+  QualifierInfo()
+    : NNS(0), NNSRange(), NumTemplParamLists(0), TemplParamLists(0) {}
+  /// setTemplateParameterListsInfo - Sets info about matched template
+  /// parameter lists.
+  void setTemplateParameterListsInfo(unsigned NumTPLists,
+                                     TemplateParameterList **TPLists);
+  /// Destructor: frees the array of template parameter lists pointers.
+  ~QualifierInfo() { delete[] TemplParamLists; }
+private:
+  // Copy constructor and copy assignment are disabled.
+  QualifierInfo(const QualifierInfo&);
+  QualifierInfo& operator=(const QualifierInfo&);
+};
+
 /// \brief Represents a ValueDecl that came out of a declarator.
 /// Contains type source information through TypeSourceInfo.
 class DeclaratorDecl : public ValueDecl {
   // A struct representing both a TInfo and a syntactic qualifier,
   // to be used for the (uncommon) case of out-of-line declarations.
-  struct ExtInfo {
+  struct ExtInfo : public QualifierInfo {
     TypeSourceInfo *TInfo;
-    NestedNameSpecifier *NNS;
-    SourceRange NNSRange;
   };
 
   llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo;
@@ -392,25 +421,37 @@
 
   TypeSourceInfo *getTypeSourceInfo() const {
     return hasExtInfo()
-      ? DeclInfo.get<ExtInfo*>()->TInfo
+      ? getExtInfo()->TInfo
       : DeclInfo.get<TypeSourceInfo*>();
   }
   void setTypeSourceInfo(TypeSourceInfo *TI) {
     if (hasExtInfo())
-      DeclInfo.get<ExtInfo*>()->TInfo = TI;
+      getExtInfo()->TInfo = TI;
     else
       DeclInfo = TI;
   }
 
   NestedNameSpecifier *getQualifier() const {
-    return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNS : 0;
+    return hasExtInfo() ? getExtInfo()->NNS : 0;
   }
   SourceRange getQualifierRange() const {
-    return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNSRange : SourceRange();
+    return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange();
   }
   void setQualifierInfo(NestedNameSpecifier *Qualifier,
                         SourceRange QualifierRange);
 
+  unsigned getNumTemplateParameterLists() const {
+    return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
+  }
+  TemplateParameterList *getTemplateParameterList(unsigned index) const {
+    assert(index < getNumTemplateParameterLists());
+    return getExtInfo()->TemplParamLists[index];
+  }
+  void setTemplateParameterListsInfo(unsigned NumTPLists,
+                                     TemplateParameterList **TPLists) {
+    getExtInfo()->setTemplateParameterListsInfo(NumTPLists, TPLists);
+  }
+
   SourceLocation getTypeSpecStartLoc() const;
 
   // Implement isa/cast/dyncast/etc.
@@ -1715,10 +1756,7 @@
 
   // A struct representing syntactic qualifier info,
   // to be used for the (uncommon) case of out-of-line declarations.
-  struct ExtInfo {
-    NestedNameSpecifier *NNS;
-    SourceRange NNSRange;
-  };
+  typedef QualifierInfo ExtInfo;
 
   /// TypedefDeclOrQualifier - If the (out-of-line) tag declaration name
   /// is qualified, it points to the qualifier info (nns and range);
@@ -1830,20 +1868,30 @@
   TypedefDecl *getTypedefForAnonDecl() const {
     return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>();
   }
-    
+
   void setTypedefForAnonDecl(TypedefDecl *TDD);
-    
+
   NestedNameSpecifier *getQualifier() const {
-    return hasExtInfo() ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNS : 0;
+    return hasExtInfo() ? getExtInfo()->NNS : 0;
   }
   SourceRange getQualifierRange() const {
-    return hasExtInfo()
-      ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNSRange
-      : SourceRange();
+    return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange();
   }
   void setQualifierInfo(NestedNameSpecifier *Qualifier,
                         SourceRange QualifierRange);
 
+  unsigned getNumTemplateParameterLists() const {
+    return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
+  }
+  TemplateParameterList *getTemplateParameterList(unsigned i) const {
+    assert(i < getNumTemplateParameterLists());
+    return getExtInfo()->TemplParamLists[i];
+  }
+  void setTemplateParameterListsInfo(unsigned NumTPLists,
+                                     TemplateParameterList **TPLists) {
+    getExtInfo()->setTemplateParameterListsInfo(NumTPLists, TPLists);
+  }
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classof(const TagDecl *D) { return true; }

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=105882&r1=105881&r2=105882&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Sat Jun 12 03:15:14 2010
@@ -566,6 +566,29 @@
   }
 }
 
+void
+QualifierInfo::setTemplateParameterListsInfo(unsigned NumTPLists,
+                                             TemplateParameterList **TPLists) {
+  assert((NumTPLists == 0 || TPLists != 0) &&
+         "Empty array of template parameters with positive size!");
+  assert((NumTPLists == 0 || NNS) &&
+         "Nonempty array of template parameters with no qualifier!");
+
+  // Free previous template parameters (if any).
+  if (NumTemplParamLists > 0) {
+    delete[] TemplParamLists;
+    TemplParamLists = 0;
+    NumTemplParamLists = 0;
+  }
+  // Set info on matched template parameter lists (if any).
+  if (NumTPLists > 0) {
+    TemplParamLists = new TemplateParameterList*[NumTPLists];
+    NumTemplParamLists = NumTPLists;
+    for (unsigned i = NumTPLists; i-- > 0; )
+      TemplParamLists[i] = TPLists[i];
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // VarDecl Implementation
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=105882&r1=105881&r2=105882&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Jun 12 03:15:14 2010
@@ -2532,6 +2532,7 @@
   // Match up the template parameter lists with the scope specifier, then
   // determine whether we have a template or a template specialization.
   bool isExplicitSpecialization = false;
+  unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
   if (TemplateParameterList *TemplateParams
         = MatchTemplateParametersToScopeSpecifier(
                                   D.getDeclSpec().getSourceRange().getBegin(),
@@ -2540,6 +2541,9 @@
                                                    TemplateParamLists.size(),
                                                   /*never a friend*/ false,
                                                   isExplicitSpecialization)) {
+    // All but one template parameter lists have been matching.
+    --NumMatchedTemplateParamLists;
+
     if (TemplateParams->size() > 0) {
       // There is no such thing as a variable template.
       Diag(D.getIdentifierLoc(), diag::err_template_variable)
@@ -2568,6 +2572,11 @@
 
   SetNestedNameSpecifier(NewVD, D);
 
+  if (NumMatchedTemplateParamLists > 0) {
+    NewVD->setTemplateParameterListsInfo(NumMatchedTemplateParamLists,
+                        (TemplateParameterList**)TemplateParamLists.release());
+  }
+
   if (D.getDeclSpec().isThreadSpecified()) {
     if (NewVD->hasLocalStorage())
       Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global);
@@ -3088,6 +3097,7 @@
   FunctionTemplateDecl *FunctionTemplate = 0;
   bool isExplicitSpecialization = false;
   bool isFunctionTemplateSpecialization = false;
+  unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
   if (TemplateParameterList *TemplateParams
         = MatchTemplateParametersToScopeSpecifier(
                                   D.getDeclSpec().getSourceRange().getBegin(),
@@ -3096,6 +3106,9 @@
                                                   TemplateParamLists.size(),
                                                   isFriend,
                                                   isExplicitSpecialization)) {
+    // All but one template parameter lists have been matching.
+    --NumMatchedTemplateParamLists;
+
     if (TemplateParams->size() > 0) {
       // This is a function template
 
@@ -3135,11 +3148,13 @@
           << FixItHint::CreateInsertion(InsertLoc, "<>");
       }
     }
+  }
 
-    // FIXME: Free this memory properly.
-    TemplateParamLists.release();
+  if (NumMatchedTemplateParamLists > 0) {
+    NewFD->setTemplateParameterListsInfo(NumMatchedTemplateParamLists,
+                        (TemplateParameterList**)TemplateParamLists.release());
   }
-  
+
   // C++ [dcl.fct.spec]p5:
   //   The virtual specifier shall only be used in declarations of
   //   nonstatic class member functions that appear within a
@@ -4965,6 +4980,7 @@
 
   // FIXME: Check explicit specializations more carefully.
   bool isExplicitSpecialization = false;
+  unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
   if (TUK != TUK_Reference) {
     if (TemplateParameterList *TemplateParams
           = MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
@@ -4972,6 +4988,9 @@
                                               TemplateParameterLists.size(),
                                                     TUK == TUK_Friend,
                                                     isExplicitSpecialization)) {
+      // All but one template parameter lists have been matching.
+      --NumMatchedTemplateParamLists;
+
       if (TemplateParams->size() > 0) {
         // This is a declaration or definition of a class template (which may
         // be a member of another template).
@@ -4989,8 +5008,6 @@
         isExplicitSpecialization = true;
       }
     }
-             
-    TemplateParameterLists.release();
   }
 
   DeclContext *SearchDC = CurContext;
@@ -5394,6 +5411,10 @@
       NestedNameSpecifier *NNS
         = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
       New->setQualifierInfo(NNS, SS.getRange());
+      if (NumMatchedTemplateParamLists > 0) {
+        New->setTemplateParameterListsInfo(NumMatchedTemplateParamLists,
+                    (TemplateParameterList**) TemplateParameterLists.release());
+      }
     }
     else
       Invalid = true;

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=105882&r1=105881&r2=105882&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sat Jun 12 03:15:14 2010
@@ -3666,6 +3666,10 @@
                                               TemplateParameterLists.size(),
                                               TUK == TUK_Friend,
                                               isExplicitSpecialization);
+  unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
+  if (TemplateParams)
+    --NumMatchedTemplateParamLists;
+
   if (TemplateParams && TemplateParams->size() > 0) {
     isPartialSpecialization = true;
 
@@ -3857,6 +3861,10 @@
                                                        PrevPartial,
                                                        SequenceNumber);
     SetNestedNameSpecifier(Partial, SS);
+    if (NumMatchedTemplateParamLists > 0) {
+      Partial->setTemplateParameterListsInfo(NumMatchedTemplateParamLists,
+                    (TemplateParameterList**) TemplateParameterLists.release());
+    }
 
     if (PrevPartial) {
       ClassTemplate->getPartialSpecializations().RemoveNode(PrevPartial);
@@ -3914,6 +3922,11 @@
                                                 Converted,
                                                 PrevDecl);
     SetNestedNameSpecifier(Specialization, SS);
+    if (NumMatchedTemplateParamLists > 0) {
+      Specialization->setTemplateParameterListsInfo(
+                    NumMatchedTemplateParamLists,
+                    (TemplateParameterList**) TemplateParameterLists.release());
+    }
 
     if (PrevDecl) {
       ClassTemplate->getSpecializations().RemoveNode(PrevDecl);





More information about the cfe-commits mailing list