]> granicus.if.org Git - clang/commitdiff
Implement proper (de-)serialization for explicit template argument
authorDouglas Gregor <dgregor@apple.com>
Fri, 4 Feb 2011 12:01:24 +0000 (12:01 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 4 Feb 2011 12:01:24 +0000 (12:01 +0000)
lists with zero template arguments. Fixes some seriously scary
crashers in C++ PCH.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124862 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
include/clang/AST/ExprCXX.h
lib/AST/Expr.cpp
lib/AST/ExprCXX.cpp
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
test/PCH/cxx-templates.cpp
test/PCH/cxx-templates.h

index e718961866b5f4a5249a01c9c4b13329ddbf0d7a..cf1faf1aff997cdc29d2fa9d6660480d19372ecd 100644 (file)
@@ -668,7 +668,9 @@ public:
 
   /// \brief Construct an empty declaration reference expression.
   static DeclRefExpr *CreateEmpty(ASTContext &Context,
-                                  bool HasQualifier, unsigned NumTemplateArgs);
+                                  bool HasQualifier, 
+                                  bool HasExplicitTemplateArgs,
+                                  unsigned NumTemplateArgs);
   
   ValueDecl *getDecl() { return DecoratedD.getPointer(); }
   const ValueDecl *getDecl() const { return DecoratedD.getPointer(); }
index addf35a1bcd8367cf64a1869c0a99357d1910ef3..7c8ac952035e00f7e7ed66287ec83d6138a82bfd 100644 (file)
@@ -1762,6 +1762,7 @@ public:
                                       UnresolvedSetIterator End);
 
   static UnresolvedLookupExpr *CreateEmpty(ASTContext &C,
+                                           bool HasExplicitTemplateArgs,
                                            unsigned NumTemplateArgs);
 
   /// True if this declaration should be extended by
@@ -1883,6 +1884,7 @@ public:
                               const TemplateArgumentListInfo *TemplateArgs = 0);
 
   static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C,
+                                                bool HasExplicitTemplateArgs,
                                                 unsigned NumTemplateArgs);
 
   /// \brief Retrieve the name that this expression refers to.
@@ -2223,7 +2225,8 @@ public:
          const TemplateArgumentListInfo *TemplateArgs);
 
   static CXXDependentScopeMemberExpr *
-  CreateEmpty(ASTContext &C, unsigned NumTemplateArgs);
+  CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs, 
+              unsigned NumTemplateArgs);
 
   /// \brief True if this is an implicit access, i.e. one in which the
   /// member being accessed was not written in the source.  The source
@@ -2445,7 +2448,8 @@ public:
          UnresolvedSetIterator Begin, UnresolvedSetIterator End);
 
   static UnresolvedMemberExpr *
-  CreateEmpty(ASTContext &C, unsigned NumTemplateArgs);
+  CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
+              unsigned NumTemplateArgs);
 
   /// \brief True if this is an implicit access, i.e. one in which the
   /// member being accessed was not written in the source.  The source
index 9e8f801791dade212a4c6e6a8785c29066e673c3..04498f7b9a9448e2d376134bbbe5f8b44f22a368 100644 (file)
@@ -319,13 +319,15 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
                                TemplateArgs, T, VK);
 }
 
-DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, bool HasQualifier,
+DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, 
+                                      bool HasQualifier,
+                                      bool HasExplicitTemplateArgs,
                                       unsigned NumTemplateArgs) {
   std::size_t Size = sizeof(DeclRefExpr);
   if (HasQualifier)
     Size += sizeof(NameQualifier);
   
-  if (NumTemplateArgs)
+  if (HasExplicitTemplateArgs)
     Size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
   
   void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
index 7cd714ba3fa754779dbfe417e533c7c8c599a705..a11d05a3a769fde06ac820bc7c77b3ae19923650 100644 (file)
@@ -265,14 +265,15 @@ UnresolvedLookupExpr::Create(ASTContext &C,
 }
 
 UnresolvedLookupExpr *
-UnresolvedLookupExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) {
+UnresolvedLookupExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs, 
+                                  unsigned NumTemplateArgs) {
   std::size_t size = sizeof(UnresolvedLookupExpr);
-  if (NumTemplateArgs != 0)
+  if (HasExplicitTemplateArgs)
     size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
 
   void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedLookupExpr>());
   UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell());
-  E->HasExplicitTemplateArgs = NumTemplateArgs != 0;
+  E->HasExplicitTemplateArgs = HasExplicitTemplateArgs;
   return E;
 }
 
@@ -417,13 +418,17 @@ DependentScopeDeclRefExpr::Create(ASTContext &C,
 
 DependentScopeDeclRefExpr *
 DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C,
+                                       bool HasExplicitTemplateArgs,
                                        unsigned NumTemplateArgs) {
   std::size_t size = sizeof(DependentScopeDeclRefExpr);
-  if (NumTemplateArgs)
+  if (HasExplicitTemplateArgs)
     size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
   void *Mem = C.Allocate(size);
-  return new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(),
-                                             DeclarationNameInfo(), 0);
+  DependentScopeDeclRefExpr *E 
+    = new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(),
+                                          DeclarationNameInfo(), 0);
+  E->HasExplicitTemplateArgs = HasExplicitTemplateArgs;
+  return E;
 }
 
 StmtIterator DependentScopeDeclRefExpr::child_begin() {
@@ -902,8 +907,9 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C,
 
 CXXDependentScopeMemberExpr *
 CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C,
+                                         bool HasExplicitTemplateArgs,
                                          unsigned NumTemplateArgs) {
-  if (NumTemplateArgs == 0)
+  if (!HasExplicitTemplateArgs)
     return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(),
                                                0, SourceLocation(), 0,
                                                SourceRange(), 0,
@@ -978,14 +984,15 @@ UnresolvedMemberExpr::Create(ASTContext &C,
 }
 
 UnresolvedMemberExpr *
-UnresolvedMemberExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) {
+UnresolvedMemberExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
+                                  unsigned NumTemplateArgs) {
   std::size_t size = sizeof(UnresolvedMemberExpr);
-  if (NumTemplateArgs != 0)
+  if (HasExplicitTemplateArgs)
     size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
 
   void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>());
   UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell());
-  E->HasExplicitTemplateArgs = NumTemplateArgs != 0;
+  E->HasExplicitTemplateArgs = HasExplicitTemplateArgs;
   return E;
 }
 
index c704eb2ab4cac33be837beb69eb8cd2b452370d2..4335ff9706807c8d725bb637f30470f6e0ce1570 100644 (file)
@@ -419,19 +419,22 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
   VisitExpr(E);
 
   bool HasQualifier = Record[Idx++];
-  unsigned NumTemplateArgs = Record[Idx++];
+  bool HasExplicitTemplateArgs = Record[Idx++];
   
   E->DecoratedD.setInt((HasQualifier? DeclRefExpr::HasQualifierFlag : 0) |
-      (NumTemplateArgs ? DeclRefExpr::HasExplicitTemplateArgumentListFlag : 0));
+      (HasExplicitTemplateArgs 
+         ? DeclRefExpr::HasExplicitTemplateArgumentListFlag : 0));
   
   if (HasQualifier) {
     E->getNameQualifier()->NNS = Reader.ReadNestedNameSpecifier(Record, Idx);
     E->getNameQualifier()->Range = ReadSourceRange(Record, Idx);
   }
 
-  if (NumTemplateArgs)
+  if (HasExplicitTemplateArgs) {
+    unsigned NumTemplateArgs = Record[Idx++];
     ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
                                      NumTemplateArgs);
+  }
 
   E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
   E->setLocation(ReadSourceLocation(Record, Idx));
@@ -1180,12 +1183,9 @@ void
 ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
   VisitExpr(E);
   
-  unsigned NumTemplateArgs = Record[Idx++];
-  assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
-         "Read wrong record during creation ?");
-  if (E->hasExplicitTemplateArgs())
+  if (Record[Idx++])
     ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
-                                     NumTemplateArgs);
+                                     Record[Idx++]);
 
   E->setBase(Reader.ReadSubExpr());
   E->setBaseType(Reader.GetType(Record[Idx++]));
@@ -1202,13 +1202,10 @@ void
 ASTStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
   VisitExpr(E);
   
-  unsigned NumTemplateArgs = Record[Idx++];
-  assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
-         "Read wrong record during creation ?");
-  if (E->hasExplicitTemplateArgs())
-    ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
-                                     NumTemplateArgs);
-
+  if (Record[Idx++])
+    ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), 
+                                     Record[Idx++]);
+  
   ReadDeclarationNameInfo(E->NameInfo, Record, Idx);
   E->setQualifierRange(ReadSourceRange(Record, Idx));
   E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
@@ -1229,12 +1226,10 @@ ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
 void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) {
   VisitExpr(E);
   
-  unsigned NumTemplateArgs = Record[Idx++];
-  assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
-         "Read wrong record during creation ?");
-  if (E->hasExplicitTemplateArgs())
+  // Read the explicit template argument list, if available.
+  if (Record[Idx++])
     ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
-                                     NumTemplateArgs);
+                                     Record[Idx++]);
 
   unsigned NumDecls = Record[Idx++];
   UnresolvedSet<8> Decls;
@@ -1484,7 +1479,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
     case EXPR_DECL_REF:
       S = DeclRefExpr::CreateEmpty(*Context,
                          /*HasQualifier=*/Record[ASTStmtReader::NumExprFields],
-                  /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1]);
+          /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1],
+                  /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1]
+                                   ? Record[ASTStmtReader::NumExprFields + 2] 
+                                   : 0);
       break;
 
     case EXPR_INTEGER_LITERAL:
@@ -1552,8 +1550,9 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
       }
 
       TemplateArgumentListInfo ArgInfo;
-      unsigned NumTemplateArgs = Record[Idx++];
-      if (NumTemplateArgs) {
+      bool HasExplicitTemplateArgs = Record[Idx++];
+      if (HasExplicitTemplateArgs) {
+        unsigned NumTemplateArgs = Record[Idx++];
         ArgInfo.setLAngleLoc(ReadSourceLocation(F, Record, Idx));
         ArgInfo.setRAngleLoc(ReadSourceLocation(F, Record, Idx));
         for (unsigned i = 0; i != NumTemplateArgs; ++i)
@@ -1575,7 +1574,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
 
       S = MemberExpr::Create(*Context, Base, IsArrow, NNS, QualifierRange,
                              MemberD, FoundDecl, MemberNameInfo,
-                             NumTemplateArgs ? &ArgInfo : 0, T, VK, OK);
+                             HasExplicitTemplateArgs ? &ArgInfo : 0, T, VK, OK);
       ReadDeclarationNameLoc(F, cast<MemberExpr>(S)->MemberDNLoc,
                              MemberD->getDeclName(), Record, Idx);
       break;
@@ -1812,12 +1811,18 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
       
     case EXPR_CXX_DEPENDENT_SCOPE_MEMBER:
       S = CXXDependentScopeMemberExpr::CreateEmpty(*Context,
-                      /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]);
+          /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields],
+                  /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
+                                   ? Record[ASTStmtReader::NumExprFields + 1] 
+                                   : 0);
       break;
       
     case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF:
       S = DependentScopeDeclRefExpr::CreateEmpty(*Context,
-                      /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]);
+          /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields],
+                  /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
+                                   ? Record[ASTStmtReader::NumExprFields + 1] 
+                                   : 0);
       break;
       
     case EXPR_CXX_UNRESOLVED_CONSTRUCT:
@@ -1827,12 +1832,18 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
       
     case EXPR_CXX_UNRESOLVED_MEMBER:
       S = UnresolvedMemberExpr::CreateEmpty(*Context,
-                      /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]);
+          /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields],
+                  /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
+                                   ? Record[ASTStmtReader::NumExprFields + 1] 
+                                   : 0);
       break;
       
     case EXPR_CXX_UNRESOLVED_LOOKUP:
       S = UnresolvedLookupExpr::CreateEmpty(*Context,
-                      /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]);
+          /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields],
+                  /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
+                                   ? Record[ASTStmtReader::NumExprFields + 1] 
+                                   : 0);
       break;
       
     case EXPR_CXX_UNARY_TYPE_TRAIT:
index 15a36701678cd8e99a3caffe9ab946c8c9e0325f..4a3bea5aaeb6222df51b50be771fcac557e3defc 100644 (file)
@@ -379,18 +379,18 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
   VisitExpr(E);
 
   Record.push_back(E->hasQualifier());
-  unsigned NumTemplateArgs = E->getNumTemplateArgs();
-  assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
-         "Template args list with no args ?");
-  Record.push_back(NumTemplateArgs);
+  Record.push_back(E->hasExplicitTemplateArgs());
 
   if (E->hasQualifier()) {
     Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
     Writer.AddSourceRange(E->getQualifierRange(), Record);
   }
 
-  if (NumTemplateArgs)
+  if (E->hasExplicitTemplateArgs()) {
+    unsigned NumTemplateArgs = E->getNumTemplateArgs();
+    Record.push_back(NumTemplateArgs);
     AddExplicitTemplateArgumentList(E->getExplicitTemplateArgs());
+  }
 
   Writer.AddDeclRef(E->getDecl(), Record);
   Writer.AddSourceLocation(E->getLocation(), Record);
@@ -545,11 +545,10 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) {
     Writer.AddSourceRange(E->getQualifierRange(), Record);
   }
 
-  unsigned NumTemplateArgs = E->getNumTemplateArgs();
-  assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
-         "Template args list with no args ?");
-  Record.push_back(NumTemplateArgs);
-  if (NumTemplateArgs) {
+  Record.push_back(E->hasExplicitTemplateArgs());
+  if (E->hasExplicitTemplateArgs()) {
+    unsigned NumTemplateArgs = E->getNumTemplateArgs();
+    Record.push_back(NumTemplateArgs);
     Writer.AddSourceLocation(E->getLAngleLoc(), Record);
     Writer.AddSourceLocation(E->getRAngleLoc(), Record);
     for (unsigned i=0; i != NumTemplateArgs; ++i)
@@ -1169,16 +1168,14 @@ void
 ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
   VisitExpr(E);
   
-  // Don't emit anything here, NumTemplateArgs must be emitted first.
+  // Don't emit anything here, hasExplicitTemplateArgs() must be
+  // emitted first.
 
+  Record.push_back(E->hasExplicitTemplateArgs());
   if (E->hasExplicitTemplateArgs()) {
     const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
-    assert(Args.NumTemplateArgs &&
-           "Num of template args was zero! AST reading will mess up!");
     Record.push_back(Args.NumTemplateArgs);
     AddExplicitTemplateArgumentList(Args);
-  } else {
-    Record.push_back(0);
   }
   
   if (!E->isImplicitAccess())
@@ -1199,16 +1196,13 @@ void
 ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
   VisitExpr(E);
   
-  // Don't emit anything here, NumTemplateArgs must be emitted first.
-
+  // Don't emit anything here, hasExplicitTemplateArgs() must be
+  // emitted first.
+  Record.push_back(E->hasExplicitTemplateArgs());
   if (E->hasExplicitTemplateArgs()) {
     const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
-    assert(Args.NumTemplateArgs &&
-           "Num of template args was zero! AST reading will mess up!");
     Record.push_back(Args.NumTemplateArgs);
     AddExplicitTemplateArgumentList(Args);
-  } else {
-    Record.push_back(0);
   }
 
   Writer.AddDeclarationNameInfo(E->NameInfo, Record);
@@ -1233,16 +1227,12 @@ ASTStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
 void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) {
   VisitExpr(E);
   
-  // Don't emit anything here, NumTemplateArgs must be emitted first.
-
+  // Don't emit anything here, hasExplicitTemplateArgs() must be emitted first.
+  Record.push_back(E->hasExplicitTemplateArgs());
   if (E->hasExplicitTemplateArgs()) {
     const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
-    assert(Args.NumTemplateArgs &&
-           "Num of template args was zero! AST reading will mess up!");
     Record.push_back(Args.NumTemplateArgs);
     AddExplicitTemplateArgumentList(Args);
-  } else {
-    Record.push_back(0);
   }
 
   Record.push_back(E->getNumDecls());
index 56b8ab7399f6bcdbbdd8c7abf4b2c26dd0779f3c..e2ad46c6595cc3f400734d3db04602bdc42a2152 100644 (file)
@@ -39,3 +39,7 @@ void test(const int (&a6)[17]) {
 template struct S4<int>;
 
 S7<int[5]> s7_5;
+
+namespace ZeroLengthExplicitTemplateArgs {
+  template void f<X>(X*);
+}
index ec8becbdc95589eedc85bc31e57febdb18ccced8..d2c820f877c6067e553dcad69893f2ef8400dcf7 100644 (file)
@@ -169,3 +169,27 @@ template<typename T>
 
 template<unsigned N>
 struct S7<int[N]> : S6<const int[N]> { };
+
+// Zero-length template argument lists
+namespace ZeroLengthExplicitTemplateArgs {
+  template<typename T> void h();
+
+  struct Y { 
+    template<typename T> void f();
+  };
+
+  template<typename T>
+    void f(T *ptr) {
+    T::template g<>(17);
+    ptr->template g2<>(17);
+    h<T>();
+    h<int>();
+    Y y;
+    y.f<int>();
+  }
+
+  struct X {
+    template<typename T> static void g(T);
+    template<typename T> void g2(T);
+  };
+}