ygao added you to the CC list for the revision "[PATCH] fixing clang crash when
reading an anonymous field initializer from a PCH file".
Hi,
This patch attempts to fix a clang crash when it tries to read in an anonymous
field initializer from a PCH file. Here is a test case:
```
// RUN: clang -cc1 -x c++ -std=c++11 -emit-pch -o header.pch source.h
// RUN: clang -cc1 -x c++ -std=c++11 -include-pch header.pch -fsyntax-only
-emit-llvm -o - source.cpp
//
// begin: source.h
struct v_t { };
struct m_t
{
struct { v_t v; }; // anonymous struct
m_t() { }
};
// end source.h
// begin source.cpp
struct foo
{
m_t *m;
void init(void);
};
void foo::init()
{
m = new m_t;
}
// end source.cpp
```
The cause of the problem is that there is no routine to create anonymous field
initializers from a PCH file. The fix is to add the missing methods.
Changes in DeclCXX.h and DeclCXX.cpp implement the missing constructors and
member functions for anonymous fields. Changes in ASTReader.cpp use the new
function to create the initializer. Also adding a new test
cxx-anonymous-struct.cpp.
Could someone review and commit the patch for me?
Thanks, Gao.
http://llvm-reviews.chandlerc.com/D890
Files:
test/PCH/cxx-anonymous-struct.cpp
test/PCH/cxx-anonymous-struct.h
include/clang/AST/DeclCXX.h
lib/AST/DeclCXX.cpp
lib/Serialization/ASTReader.cpp
Index: test/PCH/cxx-anonymous-struct.cpp
===================================================================
--- test/PCH/cxx-anonymous-struct.cpp
+++ test/PCH/cxx-anonymous-struct.cpp
@@ -0,0 +1,19 @@
+// Test this without pch.
+// RUN: %clang_cc1 -x c++ -std=c++11 -include %S/cxx-anonymous-struct.h
-fsyntax-only -emit-llvm -o - %s
+
+// Test with pch.
+// RUN: %clang_cc1 -x c++ -std=c++11 -emit-pch -o %t %S/cxx-anonymous-struct.h
+// RUN: %clang_cc1 -x c++ -std=c++11 -include-pch %t -fsyntax-only -emit-llvm
-o - %s
+
+// Clang used to crash with anonymous struct in PCH files
+
+struct foo
+{
+ m_t *m;
+ void init(void);
+};
+
+void foo::init()
+{
+ m = new m_t;
+}
Index: test/PCH/cxx-anonymous-struct.h
===================================================================
--- test/PCH/cxx-anonymous-struct.h
+++ test/PCH/cxx-anonymous-struct.h
@@ -0,0 +1,9 @@
+// Header file for PCH test cxx-anonymous-struct.cpp
+
+struct v_t { };
+
+struct m_t
+{
+ struct { v_t v; }; // anonymous struct
+ m_t() { }
+};
Index: include/clang/AST/DeclCXX.h
===================================================================
--- include/clang/AST/DeclCXX.h
+++ include/clang/AST/DeclCXX.h
@@ -1787,6 +1787,10 @@
SourceLocation MemberLoc, SourceLocation L, Expr *Init,
SourceLocation R, VarDecl **Indices, unsigned NumIndices);
+ CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R, VarDecl **Indices, unsigned NumIndices);
+
public:
/// CXXCtorInitializer - Creates a new base-class initializer.
explicit
@@ -1818,6 +1822,14 @@
Expr *Init, SourceLocation R,
VarDecl **Indices, unsigned NumIndices);
+ /// \brief Creates a new anonymous field initializer that optionally contains
+ /// array indices used to describe an elementwise initialization.
+ static CXXCtorInitializer *Create(ASTContext &Context,
+ IndirectFieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L,
+ Expr *Init, SourceLocation R,
+ VarDecl **Indices, unsigned NumIndices);
+
/// isBaseInitializer - Returns true when this initializer is
/// initializing a base class.
bool isBaseInitializer() const {
Index: lib/AST/DeclCXX.cpp
===================================================================
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -1553,6 +1553,21 @@
memcpy(MyIndices, Indices, NumIndices * sizeof(VarDecl *));
}
+CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
+ IndirectFieldDecl *Member,
+ SourceLocation MemberLoc,
+ SourceLocation L, Expr *Init,
+ SourceLocation R,
+ VarDecl **Indices,
+ unsigned NumIndices)
+ : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
+ LParenLoc(L), RParenLoc(R), IsVirtual(false),
+ IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices)
+{
+ VarDecl **MyIndices = reinterpret_cast<VarDecl **> (this + 1);
+ memcpy(MyIndices, Indices, NumIndices * sizeof(VarDecl *));
+}
+
CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context,
FieldDecl *Member,
SourceLocation MemberLoc,
@@ -1567,6 +1582,20 @@
Indices, NumIndices);
}
+CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context,
+ IndirectFieldDecl *Member,
+ SourceLocation MemberLoc,
+ SourceLocation L, Expr *Init,
+ SourceLocation R,
+ VarDecl **Indices,
+ unsigned NumIndices) {
+ void *Mem = Context.Allocate(sizeof(CXXCtorInitializer) +
+ sizeof(VarDecl *) * NumIndices,
+ llvm::alignOf<CXXCtorInitializer>());
+ return new (Mem) CXXCtorInitializer(Context, Member, MemberLoc, L, Init, R,
+ Indices, NumIndices);
+}
+
TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
if (isBaseInitializer())
return Initializee.get<TypeSourceInfo*>()->getTypeLoc();
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -6993,9 +6993,16 @@
MemberOrEllipsisLoc, LParenLoc,
Init, RParenLoc);
} else {
- BOMInit = CXXCtorInitializer::Create(Context, Member,
MemberOrEllipsisLoc,
- LParenLoc, Init, RParenLoc,
- Indices.data(), Indices.size());
+ if (Member)
+ BOMInit = CXXCtorInitializer::Create(Context, Member,
+ MemberOrEllipsisLoc,
+ LParenLoc, Init, RParenLoc,
+ Indices.data(), Indices.size());
+ else
+ BOMInit = CXXCtorInitializer::Create(Context, IndirectMember,
+ MemberOrEllipsisLoc,
+ LParenLoc, Init, RParenLoc,
+ Indices.data(), Indices.size());
}
if (IsWritten)
Index: test/PCH/cxx-anonymous-struct.cpp
===================================================================
--- test/PCH/cxx-anonymous-struct.cpp
+++ test/PCH/cxx-anonymous-struct.cpp
@@ -0,0 +1,19 @@
+// Test this without pch.
+// RUN: %clang_cc1 -x c++ -std=c++11 -include %S/cxx-anonymous-struct.h -fsyntax-only -emit-llvm -o - %s
+
+// Test with pch.
+// RUN: %clang_cc1 -x c++ -std=c++11 -emit-pch -o %t %S/cxx-anonymous-struct.h
+// RUN: %clang_cc1 -x c++ -std=c++11 -include-pch %t -fsyntax-only -emit-llvm -o - %s
+
+// Clang used to crash with anonymous struct in PCH files
+
+struct foo
+{
+ m_t *m;
+ void init(void);
+};
+
+void foo::init()
+{
+ m = new m_t;
+}
Index: test/PCH/cxx-anonymous-struct.h
===================================================================
--- test/PCH/cxx-anonymous-struct.h
+++ test/PCH/cxx-anonymous-struct.h
@@ -0,0 +1,9 @@
+// Header file for PCH test cxx-anonymous-struct.cpp
+
+struct v_t { };
+
+struct m_t
+{
+ struct { v_t v; }; // anonymous struct
+ m_t() { }
+};
Index: include/clang/AST/DeclCXX.h
===================================================================
--- include/clang/AST/DeclCXX.h
+++ include/clang/AST/DeclCXX.h
@@ -1787,6 +1787,10 @@
SourceLocation MemberLoc, SourceLocation L, Expr *Init,
SourceLocation R, VarDecl **Indices, unsigned NumIndices);
+ CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R, VarDecl **Indices, unsigned NumIndices);
+
public:
/// CXXCtorInitializer - Creates a new base-class initializer.
explicit
@@ -1818,6 +1822,14 @@
Expr *Init, SourceLocation R,
VarDecl **Indices, unsigned NumIndices);
+ /// \brief Creates a new anonymous field initializer that optionally contains
+ /// array indices used to describe an elementwise initialization.
+ static CXXCtorInitializer *Create(ASTContext &Context,
+ IndirectFieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L,
+ Expr *Init, SourceLocation R,
+ VarDecl **Indices, unsigned NumIndices);
+
/// isBaseInitializer - Returns true when this initializer is
/// initializing a base class.
bool isBaseInitializer() const {
Index: lib/AST/DeclCXX.cpp
===================================================================
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -1553,6 +1553,21 @@
memcpy(MyIndices, Indices, NumIndices * sizeof(VarDecl *));
}
+CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
+ IndirectFieldDecl *Member,
+ SourceLocation MemberLoc,
+ SourceLocation L, Expr *Init,
+ SourceLocation R,
+ VarDecl **Indices,
+ unsigned NumIndices)
+ : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
+ LParenLoc(L), RParenLoc(R), IsVirtual(false),
+ IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices)
+{
+ VarDecl **MyIndices = reinterpret_cast<VarDecl **> (this + 1);
+ memcpy(MyIndices, Indices, NumIndices * sizeof(VarDecl *));
+}
+
CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context,
FieldDecl *Member,
SourceLocation MemberLoc,
@@ -1567,6 +1582,20 @@
Indices, NumIndices);
}
+CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context,
+ IndirectFieldDecl *Member,
+ SourceLocation MemberLoc,
+ SourceLocation L, Expr *Init,
+ SourceLocation R,
+ VarDecl **Indices,
+ unsigned NumIndices) {
+ void *Mem = Context.Allocate(sizeof(CXXCtorInitializer) +
+ sizeof(VarDecl *) * NumIndices,
+ llvm::alignOf<CXXCtorInitializer>());
+ return new (Mem) CXXCtorInitializer(Context, Member, MemberLoc, L, Init, R,
+ Indices, NumIndices);
+}
+
TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
if (isBaseInitializer())
return Initializee.get<TypeSourceInfo*>()->getTypeLoc();
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -6993,9 +6993,16 @@
MemberOrEllipsisLoc, LParenLoc,
Init, RParenLoc);
} else {
- BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc,
- LParenLoc, Init, RParenLoc,
- Indices.data(), Indices.size());
+ if (Member)
+ BOMInit = CXXCtorInitializer::Create(Context, Member,
+ MemberOrEllipsisLoc,
+ LParenLoc, Init, RParenLoc,
+ Indices.data(), Indices.size());
+ else
+ BOMInit = CXXCtorInitializer::Create(Context, IndirectMember,
+ MemberOrEllipsisLoc,
+ LParenLoc, Init, RParenLoc,
+ Indices.data(), Indices.size());
}
if (IsWritten)
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits