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

Abramo Bagnara abramo.bagnara at gmail.com
Fri Mar 18 08:16:37 PDT 2011


Author: abramo
Date: Fri Mar 18 10:16:37 2011
New Revision: 127876

URL: http://llvm.org/viewvc/llvm-project?rev=127876&view=rev
Log:
Fixed inconsistency when adding TemplateParameterListsInfo.

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.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=127876&r1=127875&r2=127876&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Mar 18 10:16:37 2011
@@ -507,16 +507,24 @@
 /// name qualifier, to be used for the case of out-of-line declarations.
 struct QualifierInfo {
   NestedNameSpecifierLoc QualifierLoc;
-  /// NumTemplParamLists - The number of template parameter lists
-  /// that were matched against the template-ids occurring into the NNS.
+
+  /// NumTemplParamLists - The number of "outer" template parameter lists.
+  /// The count includes all of the template parameter lists that were matched
+  /// against the template-ids occurring into the NNS and possibly (in the
+  /// case of an explicit specialization) a final "template <>".
   unsigned NumTemplParamLists;
+
   /// TemplParamLists - A new-allocated array of size NumTemplParamLists,
-  /// containing pointers to the matched template parameter lists.
+  /// containing pointers to the "outer" template parameter lists.
+  /// It includes all of the template parameter lists that were matched
+  /// against the template-ids occurring into the NNS and possibly (in the
+  /// case of an explicit specialization) a final "template <>".
   TemplateParameterList** TemplParamLists;
 
   /// Default constructor.
   QualifierInfo() : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(0) {}
-  /// setTemplateParameterListsInfo - Sets info about matched template
+
+  /// setTemplateParameterListsInfo - Sets info about "outer" template
   /// parameter lists.
   void setTemplateParameterListsInfo(ASTContext &Context,
                                      unsigned NumTPLists,
@@ -603,9 +611,7 @@
     return getExtInfo()->TemplParamLists[index];
   }
   void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
-                                     TemplateParameterList **TPLists) {
-    getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists);
-  }
+                                     TemplateParameterList **TPLists);
 
   SourceLocation getTypeSpecStartLoc() const;
 
@@ -2238,9 +2244,7 @@
     return getExtInfo()->TemplParamLists[i];
   }
   void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
-                                     TemplateParameterList **TPLists) {
-    getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists);
-  }
+                                     TemplateParameterList **TPLists);
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=127876&r1=127875&r2=127876&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Mar 18 10:16:37 2011
@@ -961,16 +961,38 @@
   else {
     // Here Qualifier == 0, i.e., we are removing the qualifier (if any).
     if (hasExtInfo()) {
-      // Save type source info pointer.
-      TypeSourceInfo *savedTInfo = getExtInfo()->TInfo;
-      // Deallocate the extended decl info.
-      getASTContext().Deallocate(getExtInfo());
-      // Restore savedTInfo into (non-extended) decl info.
-      DeclInfo = savedTInfo;
+      if (getExtInfo()->NumTemplParamLists == 0) {
+        // Save type source info pointer.
+        TypeSourceInfo *savedTInfo = getExtInfo()->TInfo;
+        // Deallocate the extended decl info.
+        getASTContext().Deallocate(getExtInfo());
+        // Restore savedTInfo into (non-extended) decl info.
+        DeclInfo = savedTInfo;
+      }
+      else
+        getExtInfo()->QualifierLoc = QualifierLoc;
     }
   }
 }
 
+void
+DeclaratorDecl::setTemplateParameterListsInfo(ASTContext &Context,
+                                              unsigned NumTPLists,
+                                              TemplateParameterList **TPLists) {
+  assert(NumTPLists > 0);
+  // Make sure the extended decl info is allocated.
+  if (!hasExtInfo()) {
+    // Save (non-extended) type source info pointer.
+    TypeSourceInfo *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
+    // Allocate external info struct.
+    DeclInfo = new (getASTContext()) ExtInfo;
+    // Restore savedTInfo into (extended) decl info.
+    getExtInfo()->TInfo = savedTInfo;
+  }
+  // Set the template parameter lists info.
+  getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists);
+}
+
 SourceLocation DeclaratorDecl::getOuterLocStart() const {
   return getTemplateOrInnerLocStart(this);
 }
@@ -1030,8 +1052,6 @@
                                              TemplateParameterList **TPLists) {
   assert((NumTPLists == 0 || TPLists != 0) &&
          "Empty array of template parameters with positive size!");
-  assert((NumTPLists == 0 || QualifierLoc) &&
-         "Nonempty array of template parameters with no qualifier!");
 
   // Free previous template parameters (if any).
   if (NumTemplParamLists > 0) {
@@ -2100,12 +2120,28 @@
   else {
     // Here Qualifier == 0, i.e., we are removing the qualifier (if any).
     if (hasExtInfo()) {
-      getASTContext().Deallocate(getExtInfo());
-      TypedefDeclOrQualifier = (TypedefDecl*) 0;
+      if (getExtInfo()->NumTemplParamLists == 0) {
+        getASTContext().Deallocate(getExtInfo());
+        TypedefDeclOrQualifier = (TypedefDecl*) 0;
+      }
+      else
+        getExtInfo()->QualifierLoc = QualifierLoc;
     }
   }
 }
 
+void TagDecl::setTemplateParameterListsInfo(ASTContext &Context,
+                                            unsigned NumTPLists,
+                                            TemplateParameterList **TPLists) {
+  assert(NumTPLists > 0);
+  // Make sure the extended decl info is allocated.
+  if (!hasExtInfo())
+    // Allocate external info struct.
+    TypedefDeclOrQualifier = new (getASTContext()) ExtInfo;
+  // Set the template parameter lists info.
+  getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists);
+}
+
 //===----------------------------------------------------------------------===//
 // EnumDecl Implementation
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=127876&r1=127875&r2=127876&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Mar 18 10:16:37 2011
@@ -3094,7 +3094,6 @@
     // Match up the template parameter lists with the scope specifier, then
     // determine whether we have a template or a template specialization.
     isExplicitSpecialization = false;
-    unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
     bool Invalid = false;
     if (TemplateParameterList *TemplateParams
         = MatchTemplateParametersToScopeSpecifier(
@@ -3105,9 +3104,6 @@
                                                   /*never a friend*/ false,
                                                   isExplicitSpecialization,
                                                   Invalid)) {
-      // 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)
@@ -3123,7 +3119,6 @@
           << II
           << SourceRange(TemplateParams->getTemplateLoc(),
                          TemplateParams->getRAngleLoc());
-      
         isExplicitSpecialization = true;
       }
     }
@@ -3143,9 +3138,9 @@
 
     SetNestedNameSpecifier(NewVD, D);
 
-    if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
+    if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) {
       NewVD->setTemplateParameterListsInfo(Context,
-                                           NumMatchedTemplateParamLists,
+                                           TemplateParamLists.size(),
                                            TemplateParamLists.release());
     }
   }
@@ -3636,8 +3631,7 @@
   FunctionTemplateDecl *FunctionTemplate = 0;
   bool isExplicitSpecialization = false;
   bool isFunctionTemplateSpecialization = false;
-  unsigned NumMatchedTemplateParamLists = 0;
-  
+
   if (!getLangOptions().CPlusPlus) {
     // Determine whether the function was written with a
     // prototype. This true when:
@@ -3783,7 +3777,6 @@
     SetNestedNameSpecifier(NewFD, D);
     isExplicitSpecialization = false;
     isFunctionTemplateSpecialization = false;
-    NumMatchedTemplateParamLists = TemplateParamLists.size();
     if (D.isInvalidType())
       NewFD->setInvalidDecl();
     
@@ -3804,61 +3797,71 @@
                                   isFriend,
                                   isExplicitSpecialization,
                                   Invalid)) {
-          // All but one template parameter lists have been matching.
-          --NumMatchedTemplateParamLists;
+      if (TemplateParams->size() > 0) {
+        // This is a function template
 
-          if (TemplateParams->size() > 0) {
-            // This is a function template
+        // Check that we can declare a template here.
+        if (CheckTemplateDeclScope(S, TemplateParams))
+          return 0;
 
-            // Check that we can declare a template here.
-            if (CheckTemplateDeclScope(S, TemplateParams))
-              return 0;
-
-            // A destructor cannot be a template.
-            if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
-              Diag(NewFD->getLocation(), diag::err_destructor_template);
-              return 0;
-            }
-            
-            
-            FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
-                                                      NewFD->getLocation(),
-                                                      Name, TemplateParams,
-                                                      NewFD);
-            FunctionTemplate->setLexicalDeclContext(CurContext);
-            NewFD->setDescribedFunctionTemplate(FunctionTemplate);
-          } else {
-            // This is a function template specialization.
-            isFunctionTemplateSpecialization = true;
-
-            // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
-            if (isFriend && isFunctionTemplateSpecialization) {
-              // We want to remove the "template<>", found here.
-              SourceRange RemoveRange = TemplateParams->getSourceRange();
-
-              // If we remove the template<> and the name is not a
-              // template-id, we're actually silently creating a problem:
-              // the friend declaration will refer to an untemplated decl,
-              // and clearly the user wants a template specialization.  So
-              // we need to insert '<>' after the name.
-              SourceLocation InsertLoc;
-              if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
-                InsertLoc = D.getName().getSourceRange().getEnd();
-                InsertLoc = PP.getLocForEndOfToken(InsertLoc);
-              }
+        // A destructor cannot be a template.
+        if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
+          Diag(NewFD->getLocation(), diag::err_destructor_template);
+          return 0;
+        }
 
-              Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
-              << Name << RemoveRange
-              << FixItHint::CreateRemoval(RemoveRange)
-              << FixItHint::CreateInsertion(InsertLoc, "<>");
-            }
-          }
+        FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
+                                                        NewFD->getLocation(),
+                                                        Name, TemplateParams,
+                                                        NewFD);
+        FunctionTemplate->setLexicalDeclContext(CurContext);
+        NewFD->setDescribedFunctionTemplate(FunctionTemplate);
+
+        // For source fidelity, store the other template param lists.
+        if (TemplateParamLists.size() > 1) {
+          NewFD->setTemplateParameterListsInfo(Context,
+                                               TemplateParamLists.size() - 1,
+                                               TemplateParamLists.release());
         }
+      } else {
+        // This is a function template specialization.
+        isFunctionTemplateSpecialization = true;
+        // For source fidelity, store all the template param lists.
+        NewFD->setTemplateParameterListsInfo(Context,
+                                             TemplateParamLists.size(),
+                                             TemplateParamLists.release());
+
+        // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
+        if (isFriend) {
+          // We want to remove the "template<>", found here.
+          SourceRange RemoveRange = TemplateParams->getSourceRange();
+
+          // If we remove the template<> and the name is not a
+          // template-id, we're actually silently creating a problem:
+          // the friend declaration will refer to an untemplated decl,
+          // and clearly the user wants a template specialization.  So
+          // we need to insert '<>' after the name.
+          SourceLocation InsertLoc;
+          if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+            InsertLoc = D.getName().getSourceRange().getEnd();
+            InsertLoc = PP.getLocForEndOfToken(InsertLoc);
+          }
 
-    if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
-      NewFD->setTemplateParameterListsInfo(Context,
-                                           NumMatchedTemplateParamLists,
-                                           TemplateParamLists.release());
+          Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
+            << Name << RemoveRange
+            << FixItHint::CreateRemoval(RemoveRange)
+            << FixItHint::CreateInsertion(InsertLoc, "<>");
+        }
+      }
+    }
+    else {
+      // All template param lists were matched against the scope specifier:
+      // this is NOT (an explicit specialization of) a template.
+      if (TemplateParamLists.size() > 0)
+        // For source fidelity, store all the template param lists.
+        NewFD->setTemplateParameterListsInfo(Context,
+                                             TemplateParamLists.size(),
+                                             TemplateParamLists.release());
     }
 
     if (Invalid) {
@@ -4180,7 +4183,7 @@
         // are situations where these conditions don't apply and we
         // can actually do this check immediately.
         if (isFriend &&
-            (NumMatchedTemplateParamLists ||
+            (TemplateParamLists.size() ||
              D.getCXXScopeSpec().getScopeRep()->isDependent() ||
              CurContext->isDependentContext())) {
               // ignore these
@@ -6035,27 +6038,24 @@
 
   // FIXME: Check explicit specializations more carefully.
   bool isExplicitSpecialization = false;
-  unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
   bool Invalid = false;
 
   // We only need to do this matching if we have template parameters
   // or a scope specifier, which also conveniently avoids this work
   // for non-C++ cases.
-  if (NumMatchedTemplateParamLists ||
+  if (TemplateParameterLists.size() > 0 ||
       (SS.isNotEmpty() && TUK != TUK_Reference)) {
     if (TemplateParameterList *TemplateParams
           = MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
                                                 TemplateParameterLists.get(),
-                                               TemplateParameterLists.size(),
+                                                TemplateParameterLists.size(),
                                                     TUK == TUK_Friend,
                                                     isExplicitSpecialization,
                                                     Invalid)) {
-      // 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).
+
         if (Invalid)
           return 0;
 
@@ -6063,7 +6063,7 @@
         DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
                                                SS, Name, NameLoc, Attr,
                                                TemplateParams, AS,
-                                               NumMatchedTemplateParamLists,
+                                           TemplateParameterLists.size() - 1,
                  (TemplateParameterList**) TemplateParameterLists.release());
         return Result.get();
       } else {
@@ -6584,9 +6584,9 @@
   if (SS.isNotEmpty()) {
     if (SS.isSet()) {
       New->setQualifierInfo(SS.getWithLocInContext(Context));
-      if (NumMatchedTemplateParamLists > 0) {
+      if (TemplateParameterLists.size() > 0) {
         New->setTemplateParameterListsInfo(Context,
-                                           NumMatchedTemplateParamLists,
+                                           TemplateParameterLists.size(),
                     (TemplateParameterList**) TemplateParameterLists.release());
       }
     }

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=127876&r1=127875&r2=127876&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Mar 18 10:16:37 2011
@@ -6977,7 +6977,6 @@
   TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
 
   bool isExplicitSpecialization = false;
-  unsigned NumMatchedTemplateParamLists = TempParamLists.size();
   bool Invalid = false;
 
   if (TemplateParameterList *TemplateParams
@@ -6987,8 +6986,6 @@
                                                   /*friend*/ true,
                                                   isExplicitSpecialization,
                                                   Invalid)) {
-    --NumMatchedTemplateParamLists;
-
     if (TemplateParams->size() > 0) {
       // This is a declaration of a class template.
       if (Invalid)
@@ -6997,7 +6994,7 @@
       return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc,
                                 SS, Name, NameLoc, Attr,
                                 TemplateParams, AS_public,
-                                NumMatchedTemplateParamLists,
+                                TempParamLists.size() - 1,
                    (TemplateParameterList**) TempParamLists.release()).take();
     } else {
       // The "template<>" header is extraneous.
@@ -7012,7 +7009,7 @@
   assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?");
 
   bool isAllExplicitSpecializations = true;
-  for (unsigned I = 0; I != NumMatchedTemplateParamLists; ++I) {
+  for (unsigned I = TempParamLists.size(); I-- > 0; ) {
     if (TempParamLists.get()[I]->size()) {
       isAllExplicitSpecializations = false;
       break;

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=127876&r1=127875&r2=127876&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Mar 18 10:16:37 2011
@@ -1456,9 +1456,9 @@
 ///
 /// \returns the template parameter list, if any, that corresponds to the
 /// name that is preceded by the scope specifier @p SS. This template
-/// parameter list may be have template parameters (if we're declaring a
+/// parameter list may have template parameters (if we're declaring a
 /// template) or may have no template parameters (if we're declaring a
-/// template specialization), or may be NULL (if we were's declaring isn't
+/// template specialization), or may be NULL (if what we're declaring isn't
 /// itself a template).
 TemplateParameterList *
 Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
@@ -4390,6 +4390,11 @@
                                MultiTemplateParamsArg TemplateParameterLists) {
   assert(TUK != TUK_Reference && "References are not specializations");
 
+  // NOTE: KWLoc is the location of the tag keyword. This will instead
+  // store the location of the outermost template keyword in the declaration.
+  SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0
+    ? TemplateParameterLists.get()[0]->getTemplateLoc() : SourceLocation();
+
   // Find the class template we're specializing
   TemplateName Name = TemplateD.getAsVal<TemplateName>();
   ClassTemplateDecl *ClassTemplate
@@ -4420,10 +4425,6 @@
   if (Invalid)
     return true;
 
-  unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
-  if (TemplateParams)
-    --NumMatchedTemplateParamLists;
-
   if (TemplateParams && TemplateParams->size() > 0) {
     isPartialSpecialization = true;
 
@@ -4565,10 +4566,15 @@
     // Since the only prior class template specialization with these
     // arguments was referenced but not declared, or we're only
     // referencing this specialization as a friend, reuse that
-    // declaration node as our own, updating its source location to
-    // reflect our new declaration.
+    // declaration node as our own, updating its source location and
+    // the list of outer template parameters to reflect our new declaration.
     Specialization = PrevDecl;
     Specialization->setLocation(TemplateNameLoc);
+    if (TemplateParameterLists.size() > 0) {
+      Specialization->setTemplateParameterListsInfo(Context,
+                                              TemplateParameterLists.size(),
+                    (TemplateParameterList**) TemplateParameterLists.release());
+    }
     PrevDecl = 0;
     CanonType = Context.getTypeDeclType(Specialization);
   } else if (isPartialSpecialization) {
@@ -4594,7 +4600,7 @@
                                 Attr,
                                 TemplateParams,
                                 AS_none,
-                                NumMatchedTemplateParamLists,
+                                TemplateParameterLists.size() - 1,
                   (TemplateParameterList**) TemplateParameterLists.release());
     }
 
@@ -4616,9 +4622,9 @@
                                                        PrevPartial,
                                                        SequenceNumber);
     SetNestedNameSpecifier(Partial, SS);
-    if (NumMatchedTemplateParamLists > 0 && SS.isSet()) {
+    if (TemplateParameterLists.size() > 1 && SS.isSet()) {
       Partial->setTemplateParameterListsInfo(Context,
-                                             NumMatchedTemplateParamLists,
+                                             TemplateParameterLists.size() - 1,
                     (TemplateParameterList**) TemplateParameterLists.release());
     }
 
@@ -4675,9 +4681,9 @@
                                                 Converted.size(),
                                                 PrevDecl);
     SetNestedNameSpecifier(Specialization, SS);
-    if (NumMatchedTemplateParamLists > 0 && SS.isSet()) {
+    if (TemplateParameterLists.size() > 0) {
       Specialization->setTemplateParameterListsInfo(Context,
-                                                  NumMatchedTemplateParamLists,
+                                              TemplateParameterLists.size(),
                     (TemplateParameterList**) TemplateParameterLists.release());
     }
 
@@ -4747,8 +4753,7 @@
                                                 TemplateArgs, CanonType);
   if (TUK != TUK_Friend) {
     Specialization->setTypeAsWritten(WrittenTy);
-    if (TemplateParams)
-      Specialization->setTemplateKeywordLoc(TemplateParams->getTemplateLoc());
+    Specialization->setTemplateKeywordLoc(TemplateKWLoc);
   }
   TemplateArgsIn.release();
 





More information about the cfe-commits mailing list