[cfe-commits] r93420 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaOverload.cpp test/SemaCXX/overload-member-call.cpp
John McCall
rjmccall at apple.com
Wed Jan 13 19:28:57 PST 2010
Author: rjmccall
Date: Wed Jan 13 21:28:57 2010
New Revision: 93420
URL: http://llvm.org/viewvc/llvm-project?rev=93420&view=rev
Log:
Improve overload diagnostics some more by calling out qualifier mismatches
for special diagnostics. Unfortunately, the non-overload diagnostics are not
this good.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/test/SemaCXX/overload-member-call.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=93420&r1=93419&r2=93420&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Jan 13 21:28:57 2010
@@ -925,6 +925,30 @@
"function (the implicit copy assignment operator)}0%1"
" not viable: no known conversion from %2 to %3 for "
"%select{%ordinal5 argument|object argument}4">;
+def note_ovl_candidate_bad_addrspace : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)}0%1 not viable: "
+ "%select{%ordinal6|'this'}5 argument (%2) is in "
+ "address space %3, but parameter must be in address space %4">;
+def note_ovl_candidate_bad_cvr_this : Note<"candidate "
+ "%select{|function|||function||||"
+ "function (the implicit copy assignment operator)}0 not viable: "
+ "'this' argument has type %2, but method is not marked "
+ "%select{const|volatile|const or volatile|restrict|const or restrict|"
+ "volatile or restrict|const, volatile, or restrict}3">;
+def note_ovl_candidate_bad_cvr : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)}0%1 not viable: "
+ "%ordinal4 argument (%2) would lose "
+ "%select{const|volatile|const and volatile|restrict|const and restrict|"
+ "volatile and restrict|const, volatile, and restrict}3 qualifier"
+ "%select{||s||s|s|s}3">;
def note_ambiguous_type_conversion: Note<
"because of ambiguity in conversion of %0 to %1">;
def note_ovl_builtin_binary_candidate : Note<
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=93420&r1=93419&r2=93420&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Jan 13 21:28:57 2010
@@ -2191,7 +2191,7 @@
/// parameter of the given member function (@c Method) from the
/// expression @p From.
ImplicitConversionSequence
-Sema::TryObjectArgumentInitialization(QualType FromType,
+Sema::TryObjectArgumentInitialization(QualType OrigFromType,
CXXMethodDecl *Method,
CXXRecordDecl *ActingContext) {
QualType ClassType = Context.getTypeDeclType(ActingContext);
@@ -2208,6 +2208,7 @@
ICS.setBad();
// We need to have an object of class type.
+ QualType FromType = OrigFromType;
if (const PointerType *PT = FromType->getAs<PointerType>())
FromType = PT->getPointeeType();
@@ -2228,7 +2229,8 @@
if (ImplicitParamType.getCVRQualifiers()
!= FromTypeCanon.getLocalCVRQualifiers() &&
!ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) {
- ICS.Bad.init(BadConversionSequence::bad_qualifiers, FromType, ImplicitParamType);
+ ICS.Bad.init(BadConversionSequence::bad_qualifiers,
+ OrigFromType, ImplicitParamType);
return ICS;
}
@@ -4384,7 +4386,57 @@
QualType FromTy = Conv.Bad.getFromType();
QualType ToTy = Conv.Bad.getToType();
- // TODO: specialize based on the kind of mismatch
+ // Do some hand-waving analysis to see if the non-viability is due to a
+ CanQualType CFromTy = S.Context.getCanonicalType(FromTy);
+ CanQualType CToTy = S.Context.getCanonicalType(ToTy);
+ if (CanQual<ReferenceType> RT = CToTy->getAs<ReferenceType>())
+ CToTy = RT->getPointeeType();
+ else {
+ // TODO: detect and diagnose the full richness of const mismatches.
+ if (CanQual<PointerType> FromPT = CFromTy->getAs<PointerType>())
+ if (CanQual<PointerType> ToPT = CToTy->getAs<PointerType>())
+ CFromTy = FromPT->getPointeeType(), CToTy = ToPT->getPointeeType();
+ }
+
+ if (CToTy.getUnqualifiedType() == CFromTy.getUnqualifiedType() &&
+ !CToTy.isAtLeastAsQualifiedAs(CFromTy)) {
+ // It is dumb that we have to do this here.
+ while (isa<ArrayType>(CFromTy))
+ CFromTy = CFromTy->getAs<ArrayType>()->getElementType();
+ while (isa<ArrayType>(CToTy))
+ CToTy = CFromTy->getAs<ArrayType>()->getElementType();
+
+ Qualifiers FromQs = CFromTy.getQualifiers();
+ Qualifiers ToQs = CToTy.getQualifiers();
+
+ if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) {
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy
+ << FromQs.getAddressSpace() << ToQs.getAddressSpace()
+ << (unsigned) isObjectArgument << I+1;
+ return;
+ }
+
+ unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
+ assert(CVR && "unexpected qualifiers mismatch");
+
+ if (isObjectArgument) {
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy << (CVR - 1);
+ } else {
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy << (CVR - 1) << I+1;
+ }
+ return;
+ }
+
+ // TODO: specialize more based on the kind of mismatch
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv)
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
Modified: cfe/trunk/test/SemaCXX/overload-member-call.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-member-call.cpp?rev=93420&r1=93419&r2=93420&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overload-member-call.cpp (original)
+++ cfe/trunk/test/SemaCXX/overload-member-call.cpp Wed Jan 13 21:28:57 2010
@@ -78,8 +78,11 @@
void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}}
void foo(int n, const char *s, int t, int u = 0); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}}
- void bar(double d); //expected-note {{candidate function not viable: no known conversion from 'class test1::A const' to 'class test1::A' for object argument}}
- void bar(int i); //expected-note {{candidate function not viable: no known conversion from 'class test1::A const' to 'class test1::A' for object argument}}
+ void bar(double d); //expected-note {{candidate function not viable: 'this' argument has type 'class test1::A const', but method is not marked const}}
+ void bar(int i); //expected-note {{candidate function not viable: 'this' argument has type 'class test1::A const', but method is not marked const}}
+
+ void baz(A &d); // expected-note {{candidate function not viable: 1st argument ('class test1::A const') would lose const qualifier}}
+ void baz(int i); // expected-note {{candidate function not viable: no known conversion from 'class test1::A const' to 'int' for 1st argument}}
};
void test() {
@@ -88,6 +91,8 @@
const A b;
b.bar(0); //expected-error {{no matching member function for call to 'bar'}}
+
+ a.baz(b); //expected-error {{no matching member function for call to 'baz'}}
}
}
More information about the cfe-commits
mailing list