diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 9bf417c7b133..e39fe3ba739e 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/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/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 21f1d512532f..a0ecf2792124 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/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/clang/test/PCH/cxx-templates.cpp b/clang/test/PCH/cxx-templates.cpp index cd48666ce0d6..982fc67e4e8a 100644 --- a/clang/test/PCH/cxx-templates.cpp +++ b/clang/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); + } + }; +}