teemperor created this revision.
teemperor added reviewers: cfe-commits, rnk.

  Fix crash in BuildCXXDefaultInitExpr when member of template class
  has same name as the class itself.

http://reviews.llvm.org/D19721

Files:
  lib/Sema/SemaDeclCXX.cpp
  test/SemaCXX/pr27047-default-init-expr-name-conflict.cpp

Index: test/SemaCXX/pr27047-default-init-expr-name-conflict.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/pr27047-default-init-expr-name-conflict.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s
+
+struct A {};
+
+template <typename T>
+struct B {
+
+  // Don't crash here
+  A B{};
+};
+
+int main() {
+  B<int> b;
+}
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -11412,8 +11412,31 @@
     CXXRecordDecl *ClassPattern = ParentRD->getTemplateInstantiationPattern();
     DeclContext::lookup_result Lookup =
         ClassPattern->lookup(Field->getDeclName());
-    assert(Lookup.size() == 1);
-    FieldDecl *Pattern = cast<FieldDecl>(Lookup[0]);
+
+    FieldDecl *Pattern = nullptr;
+
+    // It's possible that both the current CXXRecordDecl and
+    // the wanted FieldDecl appear in Lookup, so we iterate
+    // over it and check that there is exactly one FieldDecl
+    // and an optional unused CXXRecordDecl.
+    for (NamedDecl *PossibleDecl : Lookup) {
+      FieldDecl *PossibleFieldDecl = dyn_cast<FieldDecl>(PossibleDecl);
+
+      if (PossibleFieldDecl) {
+        // Will fail if there is more than one FieldDecl in Lookup.
+        assert(Pattern == nullptr);
+
+        Pattern = PossibleFieldDecl;
+      } else {
+        // Assert that the other declaration is the unused
+        // parent CXXRecordDecl.
+        assert(isa<CXXRecordDecl>(PossibleDecl));
+      }
+    }
+
+    // Will fail if there is no FieldDecl in Lookup.
+    assert(Pattern != nullptr);
+
     if (InstantiateInClassInitializer(Loc, Field, Pattern,
                                       getTemplateInstantiationArgs(Field)))
       return ExprError();


Index: test/SemaCXX/pr27047-default-init-expr-name-conflict.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/pr27047-default-init-expr-name-conflict.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s
+
+struct A {};
+
+template <typename T>
+struct B {
+
+  // Don't crash here
+  A B{};
+};
+
+int main() {
+  B<int> b;
+}
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -11412,8 +11412,31 @@
     CXXRecordDecl *ClassPattern = ParentRD->getTemplateInstantiationPattern();
     DeclContext::lookup_result Lookup =
         ClassPattern->lookup(Field->getDeclName());
-    assert(Lookup.size() == 1);
-    FieldDecl *Pattern = cast<FieldDecl>(Lookup[0]);
+
+    FieldDecl *Pattern = nullptr;
+
+    // It's possible that both the current CXXRecordDecl and
+    // the wanted FieldDecl appear in Lookup, so we iterate
+    // over it and check that there is exactly one FieldDecl
+    // and an optional unused CXXRecordDecl.
+    for (NamedDecl *PossibleDecl : Lookup) {
+      FieldDecl *PossibleFieldDecl = dyn_cast<FieldDecl>(PossibleDecl);
+
+      if (PossibleFieldDecl) {
+        // Will fail if there is more than one FieldDecl in Lookup.
+        assert(Pattern == nullptr);
+
+        Pattern = PossibleFieldDecl;
+      } else {
+        // Assert that the other declaration is the unused
+        // parent CXXRecordDecl.
+        assert(isa<CXXRecordDecl>(PossibleDecl));
+      }
+    }
+
+    // Will fail if there is no FieldDecl in Lookup.
+    assert(Pattern != nullptr);
+
     if (InstantiateInClassInitializer(Loc, Field, Pattern,
                                       getTemplateInstantiationArgs(Field)))
       return ExprError();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to