From 64cf3efd47bc79b661c93cea5a7a3fa60bba16d8 Mon Sep 17 00:00:00 2001 From: Larisse Voufo Date: Thu, 27 Jun 2013 01:50:25 +0000 Subject: [PATCH] Fix a conversion to incomplete type bug -- The error message now specifically states that the type is incomplete and points to the forward declaration of the incomplete type. llvm-svn: 185056 --- .../clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaInit.cpp | 12 +++++++--- clang/lib/Sema/SemaOverload.cpp | 13 +++++++---- .../SemaCXX/conversion-incomplete-type.cpp | 23 +++++++++++++++++++ 4 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 clang/test/SemaCXX/conversion-incomplete-type.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5428550e85fd..54157b317abe 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5014,6 +5014,8 @@ def err_typecheck_ambiguous_condition : Error< "conversion %diff{from $ to $|between types}0,1 is ambiguous">; def err_typecheck_nonviable_condition : Error< "no viable conversion%diff{ from $ to $|}0,1">; +def err_typecheck_nonviable_condition_incomplete : Error< + "no viable conversion%diff{ from $ to incomplete type $|}0,1">; def err_typecheck_deleted_function : Error< "conversion function %diff{from $ to $|between types}0,1 " "invokes a deleted function">; diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 9d7fcda8fddd..cbca84da9257 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -6251,9 +6251,15 @@ bool InitializationSequence::Diagnose(Sema &S, break; case OR_No_Viable_Function: - S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) - << Args[0]->getType() << DestType.getNonReferenceType() - << Args[0]->getSourceRange(); + if (!DestType.getNonReferenceType()->isIncompleteType() || + !S.RequireCompleteType(Kind.getLocation(), + DestType.getNonReferenceType(), + diag::err_typecheck_nonviable_condition_incomplete, + Args[0]->getType(), Args[0]->getSourceRange())) + S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) + << Args[0]->getType() << Args[0]->getSourceRange() + << DestType.getNonReferenceType(); + FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args); break; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index d4d08b4bff8d..b1fe76a8f61a 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -3231,10 +3231,15 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { Diag(From->getLocStart(), diag::err_typecheck_ambiguous_condition) << From->getType() << ToType << From->getSourceRange(); - else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) - Diag(From->getLocStart(), - diag::err_typecheck_nonviable_condition) - << From->getType() << ToType << From->getSourceRange(); + else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) { + if (!ToType->isIncompleteType() || + !RequireCompleteType(From->getLocStart(), ToType, + diag::err_typecheck_nonviable_condition_incomplete, + From->getType(), From->getSourceRange())) + Diag(From->getLocStart(), + diag::err_typecheck_nonviable_condition) + << From->getType() << From->getSourceRange() << ToType; + } else return false; CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From); diff --git a/clang/test/SemaCXX/conversion-incomplete-type.cpp b/clang/test/SemaCXX/conversion-incomplete-type.cpp new file mode 100644 index 000000000000..ebedd04047b9 --- /dev/null +++ b/clang/test/SemaCXX/conversion-incomplete-type.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct string {}; + +class StringPiece; // expected-note {{forward declaration of 'StringPiece'}} \ + // expected-note {{forward declaration of 'StringPiece'}} + +struct Test { + void expectStringPiece(const StringPiece& blah) {}; // expected-note {{passing argument to parameter 'blah' here}} + + void test(const string& s) { + expectStringPiece(s); // expected-error {{no viable conversion from 'const string' to incomplete type 'const StringPiece'}} + } +}; + +struct TestStatic { + static void expectStringPiece(const StringPiece& blah) {}; // expected-note {{passing argument to parameter 'blah' here}} + + static void test(const string& s) { + expectStringPiece(s); // expected-error {{no viable conversion from 'const string' to incomplete type 'const StringPiece'}} + } +}; +