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