From b0ca137bf399d956a3424816c238bc2532250d17 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sun, 6 Mar 2011 18:19:42 +0000 Subject: [PATCH] When serializing a DeclRefExpr, always store the number of explicit template arguments at the same offset, since it's needed when creating the empty DeclRefExpr when deserializing. Fixes a memory corruption issue that would lead to random bugs and crashes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127125 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Serialization/ASTReaderStmt.cpp | 12 ++++++------ lib/Serialization/ASTWriterStmt.cpp | 10 ++++++---- test/PCH/cxx-templates.cpp | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 9bf417c7b1..e39fe3ba73 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -423,21 +423,21 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { bool HasQualifier = Record[Idx++]; bool HasExplicitTemplateArgs = Record[Idx++]; - + unsigned NumTemplateArgs = 0; + if (HasExplicitTemplateArgs) + NumTemplateArgs = Record[Idx++]; + E->DecoratedD.setInt((HasQualifier? DeclRefExpr::HasQualifierFlag : 0) | (HasExplicitTemplateArgs ? DeclRefExpr::HasExplicitTemplateArgumentListFlag : 0)); - if (HasQualifier) { + if (HasQualifier) E->getNameQualifier()->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); - } - if (HasExplicitTemplateArgs) { - unsigned NumTemplateArgs = Record[Idx++]; + if (HasExplicitTemplateArgs) ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), NumTemplateArgs); - } E->setDecl(cast(Reader.GetDecl(Record[Idx++]))); E->setLocation(ReadSourceLocation(Record, Idx)); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 21f1d51253..a0ecf27921 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -382,15 +382,17 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { Record.push_back(E->hasQualifier()); Record.push_back(E->hasExplicitTemplateArgs()); - if (E->hasQualifier()) - Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); - if (E->hasExplicitTemplateArgs()) { unsigned NumTemplateArgs = E->getNumTemplateArgs(); Record.push_back(NumTemplateArgs); - AddExplicitTemplateArgumentList(E->getExplicitTemplateArgs()); } + if (E->hasQualifier()) + Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); + + if (E->hasExplicitTemplateArgs()) + AddExplicitTemplateArgumentList(E->getExplicitTemplateArgs()); + Writer.AddDeclRef(E->getDecl(), Record); Writer.AddSourceLocation(E->getLocation(), Record); Writer.AddDeclarationNameLoc(E->DNLoc, E->getDecl()->getDeclName(), Record); diff --git a/test/PCH/cxx-templates.cpp b/test/PCH/cxx-templates.cpp index cd48666ce0..982fc67e4e 100644 --- a/test/PCH/cxx-templates.cpp +++ b/test/PCH/cxx-templates.cpp @@ -43,3 +43,22 @@ S7 s7_5; namespace ZeroLengthExplicitTemplateArgs { template void f(X*); } + +// This used to overwrite memory and crash. +namespace Test1 { + struct StringHasher { + template static inline unsigned createHash(const T*, unsigned) { + return 0; + } + }; + + struct CaseFoldingHash { + static inline char foldCase(char) { + return 0; + } + + static unsigned hash(const char* data, unsigned length) { + return StringHasher::createHash(data, length); + } + }; +} -- 2.40.0