DR1687: When overload resolution selects a built-in operator, implicit
conversions are only applied to operands of class type, and the second
standard conversion sequence is not applied.
When diagnosing an invalid builtin binary operator, talk about the
original types rather than the converted types. If these differ by a
user-defined conversion, tell the user what happened.
llvm-svn: 335781
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 47cf026..3d11619 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1673,23 +1673,22 @@
}
namespace {
- Expr *skipImplicitTemporary(Expr *expr) {
+ const Expr *skipImplicitTemporary(const Expr *E) {
// Skip through reference binding to temporary.
- if (MaterializeTemporaryExpr *Materialize
- = dyn_cast<MaterializeTemporaryExpr>(expr))
- expr = Materialize->GetTemporaryExpr();
+ if (auto *Materialize = dyn_cast<MaterializeTemporaryExpr>(E))
+ E = Materialize->GetTemporaryExpr();
// Skip any temporary bindings; they're implicit.
- if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(expr))
- expr = Binder->getSubExpr();
+ if (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
+ E = Binder->getSubExpr();
- return expr;
+ return E;
}
}
Expr *CastExpr::getSubExprAsWritten() {
- Expr *SubExpr = nullptr;
- CastExpr *E = this;
+ const Expr *SubExpr = nullptr;
+ const CastExpr *E = this;
do {
SubExpr = skipImplicitTemporary(E->getSubExpr());
@@ -1702,15 +1701,33 @@
assert((isa<CXXMemberCallExpr>(SubExpr) ||
isa<BlockExpr>(SubExpr)) &&
"Unexpected SubExpr for CK_UserDefinedConversion.");
- if (isa<CXXMemberCallExpr>(SubExpr))
- SubExpr = cast<CXXMemberCallExpr>(SubExpr)->getImplicitObjectArgument();
+ if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SubExpr))
+ SubExpr = MCE->getImplicitObjectArgument();
}
// If the subexpression we're left with is an implicit cast, look
// through that, too.
} while ((E = dyn_cast<ImplicitCastExpr>(SubExpr)));
- return SubExpr;
+ return const_cast<Expr*>(SubExpr);
+}
+
+NamedDecl *CastExpr::getConversionFunction() const {
+ const Expr *SubExpr = nullptr;
+
+ for (const CastExpr *E = this; E; E = dyn_cast<ImplicitCastExpr>(SubExpr)) {
+ SubExpr = skipImplicitTemporary(E->getSubExpr());
+
+ if (E->getCastKind() == CK_ConstructorConversion)
+ return cast<CXXConstructExpr>(SubExpr)->getConstructor();
+
+ if (E->getCastKind() == CK_UserDefinedConversion) {
+ if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SubExpr))
+ return MCE->getMethodDecl();
+ }
+ }
+
+ return nullptr;
}
CXXBaseSpecifier **CastExpr::path_buffer() {