diff options
-rw-r--r-- | lib/AST/DeclCXX.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 46 | ||||
-rw-r--r-- | test/SemaCXX/conversion-delete-expr.cpp | 7 | ||||
-rw-r--r-- | test/SemaCXX/direct-initializer.cpp | 8 |
4 files changed, 30 insertions, 36 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 8755067137..c979acd6eb 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -314,7 +314,7 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD) { else TConvType = getASTContext().getCanonicalType( - cast<FunctionDecl>(TopConv)->getType()); + cast<CXXConversionDecl>(TopConv)->getConversionType()); TopConversionsTypeSet.insert(TConvType); } } @@ -334,7 +334,8 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD) { ConversionTemplate->getTemplatedDecl()->getType()); else ConvType = - getASTContext().getCanonicalType(cast<FunctionDecl>(Conv)->getType()); + getASTContext().getCanonicalType( + cast<CXXConversionDecl>(Conv)->getConversionType()); if (inTopClass || !TopConversionsTypeSet.count(ConvType)) { if (FunctionTemplateDecl *ConversionTemplate = dyn_cast<FunctionTemplateDecl>(Conv)) diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 9005566ee4..0054af3493 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -736,7 +736,6 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, QualType Type = Ex->getType(); if (const RecordType *Record = Type->getAs<RecordType>()) { - OverloadCandidateSet CandidateSet; llvm::SmallVector<CXXConversionDecl *, 4> ObjectPtrConversions; CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); OverloadedFunctionDecl *Conversions = @@ -755,32 +754,27 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, QualType ConvType = Conv->getConversionType().getNonReferenceType(); if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>()) if (ConvPtrType->getPointeeType()->isObjectType()) - AddConversionCandidate(Conv, Ex, ConvType, CandidateSet); + ObjectPtrConversions.push_back(Conv); } - OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Ex->getLocStart(), Best)) { - case OR_Success: - { - Operand.release(); - CXXConversionDecl *Conversion - = cast<CXXConversionDecl>(Best->Function); - if (PerformImplicitConversion(Ex, - Conversion->getConversionType(), - "converting")) - return ExprError(); - - Operand = Owned(Ex); - Type = Ex->getType(); - break; - } - case OR_No_Viable_Function: - case OR_Deleted: - break; // Will issue error below. - case OR_Ambiguous: - Diag(StartLoc, diag::err_ambiguous_delete_operand) - << Type << Ex->getSourceRange(); - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); - return ExprError(); + if (ObjectPtrConversions.size() == 1) { + // We have a single conversion to a pointer-to-object type. Perform + // that conversion. + Operand.release(); + if (!PerformImplicitConversion(Ex, + ObjectPtrConversions.front()->getConversionType(), + "converting")) { + Operand = Owned(Ex); + Type = Ex->getType(); + } + } + else if (ObjectPtrConversions.size() > 1) { + Diag(StartLoc, diag::err_ambiguous_delete_operand) + << Type << Ex->getSourceRange(); + for (unsigned i= 0; i < ObjectPtrConversions.size(); i++) { + CXXConversionDecl *Conv = ObjectPtrConversions[i]; + Diag(Conv->getLocation(), diag::err_ovl_candidate); + } + return ExprError(); } } diff --git a/test/SemaCXX/conversion-delete-expr.cpp b/test/SemaCXX/conversion-delete-expr.cpp index 63a9765396..708289c362 100644 --- a/test/SemaCXX/conversion-delete-expr.cpp +++ b/test/SemaCXX/conversion-delete-expr.cpp @@ -78,19 +78,18 @@ void f5(X1 x) { delete x; } // OK. In selecting a conversion to pointer functio // Test7 struct Base { - operator int*(); // expected-note {{candidate function}} + operator int*(); }; struct Derived : Base { // not the same function as Base's non-const operator int() - operator int*() const; // expected-note {{candidate function}} + operator int*() const; }; void foo6(const Derived cd, Derived d) { // overload resolution selects Derived::operator int*() const; delete cd; - - delete d; // expected-error {{ambiguous conversion of delete expression of type 'struct Derived' to a pointer}} + delete d; } // Test8 diff --git a/test/SemaCXX/direct-initializer.cpp b/test/SemaCXX/direct-initializer.cpp index e95ba22769..a9e2b2bb6e 100644 --- a/test/SemaCXX/direct-initializer.cpp +++ b/test/SemaCXX/direct-initializer.cpp @@ -36,15 +36,15 @@ void g() { } struct Base { - operator int*() const; // expected-note {{candidate function}} + operator int*() const; }; struct Derived : Base { - operator int*(); // expected-note {{candidate function}} + operator int*(); }; void foo(const Derived cd, Derived d) { - int *pi = cd; - int *ppi = d; // expected-error {{ambiguity in initializing value of type 'int *' with initializer of type 'struct Derived'}} + int *pi = cd; // expected-error {{incompatible type initializing 'struct Derived const', expected 'int *'}} + int *ppi = d; } |