[PATCH] [PATCH] fixing clang crash when reading an anonymous field initializer from a PCH file

Yunzhong Gao Yunzhong_Gao at playstation.sony.com
Thu May 30 10:29:41 PDT 2013


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)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D890.1.patch
Type: text/x-patch
Size: 6055 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130530/850f3e55/attachment.bin>


More information about the cfe-commits mailing list