Index: clang/lib/Sema/SemaInit.cpp =================================================================== --- clang/lib/Sema/SemaInit.cpp +++ clang/lib/Sema/SemaInit.cpp @@ -4535,39 +4535,41 @@ S.isCompleteType(Kind.getLocation(), T2)) { // The type we're converting from is a class type, enumerate its conversion // functions. - CXXRecordDecl *T2RecordDecl = cast(T2RecordType->getDecl()); - - const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions(); - for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { - NamedDecl *D = *I; - CXXRecordDecl *ActingDC = cast(D->getDeclContext()); - if (isa(D)) - D = cast(D)->getTargetDecl(); - - FunctionTemplateDecl *ConvTemplate = dyn_cast(D); - CXXConversionDecl *Conv; - if (ConvTemplate) - Conv = cast(ConvTemplate->getTemplatedDecl()); - else - Conv = cast(D); - - // If the conversion function doesn't return a reference type, - // it can't be considered for this conversion unless we're allowed to - // consider rvalues. - // FIXME: Do we need to make sure that we only consider conversion - // candidates with reference-compatible results? That might be needed to - // break recursion. - if ((AllowRValues || - Conv->getConversionType()->isLValueReferenceType())) { + if (CXXRecordDecl *T2RecordDecl = + dyn_cast(T2RecordType->getDecl())) { + const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions(); + for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { + NamedDecl *D = *I; + CXXRecordDecl *ActingDC = cast(D->getDeclContext()); + if (isa(D)) + D = cast(D)->getTargetDecl(); + + FunctionTemplateDecl *ConvTemplate = dyn_cast(D); + CXXConversionDecl *Conv; if (ConvTemplate) - S.AddTemplateConversionCandidate( - ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, - CandidateSet, - /*AllowObjCConversionOnExplicit=*/false, AllowExplicitConvs); + Conv = cast(ConvTemplate->getTemplatedDecl()); else - S.AddConversionCandidate( - Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, - /*AllowObjCConversionOnExplicit=*/false, AllowExplicitConvs); + Conv = cast(D); + + // If the conversion function doesn't return a reference type, + // it can't be considered for this conversion unless we're allowed to + // consider rvalues. + // FIXME: Do we need to make sure that we only consider conversion + // candidates with reference-compatible results? That might be needed + // to break recursion. + if ((AllowRValues || + Conv->getConversionType()->isLValueReferenceType())) { + if (ConvTemplate) + S.AddTemplateConversionCandidate( + ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, + CandidateSet, + /*AllowObjCConversionOnExplicit=*/false, AllowExplicitConvs); + else + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, + DestType, CandidateSet, + /*AllowObjCConversionOnExplicit=*/false, + AllowExplicitConvs); + } } } } Index: clang/test/Sema/init-ref-c.c =================================================================== --- /dev/null +++ clang/test/Sema/init-ref-c.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -triple arm-unknown-gnu -fsyntax-only -verify %s + +void f() { + struct EmptyStruct {}; + struct EmptyStruct S; + __builtin_va_end(S); // no-crash, expected-error {{non-const lvalue reference to type '__builtin_va_list' cannot bind to a value of unrelated type 'struct EmptyStruct'}} +} \ No newline at end of file