def err_objc_object_assignment : Error<
"cannot assign to class object (%0 invalid)">;
def err_typecheck_invalid_operands : Error<
- "invalid operands to binary expression (%0 and %1)">;
+ "invalid operands to binary expression (%0 and %1)">, Deferrable;
def note_typecheck_invalid_operands_converted : Note<
"%select{first|second}0 operand was implicitly converted to type %1">;
def err_typecheck_logical_vector_expr_gnu_cpp_restrict : Error<
void destroyCandidates();
- /// Whether diagnostics should be deferred.
- bool shouldDeferDiags(Sema &S, ArrayRef<Expr *> Args, SourceLocation OpLoc);
-
public:
OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK,
OperatorRewriteInfo RewriteInfo = {})
CandidateSetKind getKind() const { return Kind; }
OperatorRewriteInfo getRewriteInfo() const { return RewriteInfo; }
+ /// Whether diagnostics should be deferred.
+ bool shouldDeferDiags(Sema &S, ArrayRef<Expr *> Args, SourceLocation OpLoc);
+
/// Determine when this overload candidate will be new to the
/// overload set.
bool isNewCandidate(Decl *F, OverloadCandidateParamOrder PO =
/// Build a partial diagnostic.
PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h
+ /// Whether deferrable diagnostics should be deferred.
+ bool DeferDiags = false;
+
+ /// RAII class to control scope of DeferDiags.
+ class DeferDiagsRAII {
+ Sema &S;
+ bool SavedDeferDiags = false;
+
+ public:
+ DeferDiagsRAII(Sema &_S, bool DeferDiags)
+ : S(_S), SavedDeferDiags(S.DeferDiags) {
+ S.DeferDiags = DeferDiags;
+ }
+ ~DeferDiagsRAII() { S.DeferDiags = SavedDeferDiags; }
+ };
+
/// Whether uncompilable error has occurred. This includes error happens
/// in deferred diagnostics.
bool hasUncompilableErrorOccurred() const;
bool IsError = Diags.getDiagnosticIDs()->isDefaultMappingAsError(DiagID);
bool ShouldDefer = getLangOpts().CUDA && LangOpts.GPUDeferDiag &&
DiagnosticIDs::isDeferrable(DiagID) &&
- (DeferHint || !IsError);
+ (DeferHint || DeferDiags || !IsError);
auto SetIsLastErrorImmediate = [&](bool Flag) {
if (IsError)
IsLastErrorImmediate = Flag;
CompleteCandidates(S, OCD_AllCandidates, Args, OpLoc, [](auto &Cand) {
return (Cand.Viable == false &&
Cand.FailureKind == ovl_fail_bad_target) ||
- (Cand.Function->template hasAttr<CUDAHostAttr>() &&
+ (Cand.Function &&
+ Cand.Function->template hasAttr<CUDAHostAttr>() &&
Cand.Function->template hasAttr<CUDADeviceAttr>());
});
DeferHint = !WrongSidedCands.empty();
StringRef OpcStr = BinaryOperator::getOpcodeStr(Opc);
auto Cands = CandidateSet.CompleteCandidates(*this, OCD_AllCandidates,
Args, OpLoc);
+ DeferDiagsRAII DDR(*this,
+ CandidateSet.shouldDeferDiags(*this, Args, OpLoc));
if (Args[0]->getType()->isRecordType() &&
Opc >= BO_Assign && Opc <= BO_OrAssign) {
Diag(OpLoc, diag::err_ovl_no_viable_oper)
// RUN: %clang_cc1 -fopenmp -fsyntax-only -verify=host,com %s \
// RUN: -std=c++11 -fgpu-defer-diag
+// With -fgpu-defer-diag, clang defers overloading resolution induced
+// diagnostics when the full candidates set include host device
+// functions or wrong-sided candidates. This roughly matches nvcc's
+// behavior.
+
#include "Inputs/cuda.h"
// When callee is called by a host function with integer arguments, there is an error for ambiguity.
__host__ void callee5(float); // com-note {{candidate function}}
__host__ void callee5(double); // com-note {{candidate function}}
+// When '<<` operator is called by a device function, there is error for 'invalid operands'.
+// It should be deferred since it involves wrong-sided candidates.
+struct S {
+ __host__ S &operator <<(int i); // dev-note {{candidate function not viable}}
+};
+
__host__ void hf() {
callee(1); // host-error {{call to 'callee' is ambiguous}}
callee2();
callee3();
callee4(); // com-error {{no matching function for call to 'callee4'}}
callee5(1); // com-error {{call to 'callee5' is ambiguous}}
+ S s;
+ s << 1;
undeclared_func(); // com-error {{use of undeclared identifier 'undeclared_func'}}
}
callee2(); // dev-error {{no matching function for call to 'callee2'}}
callee3(); // dev-error {{no matching function for call to 'callee3'}}
callee4(); // com-error {{no matching function for call to 'callee4'}}
+ S s;
+ s << 1; // dev-error {{invalid operands to binary expression}}
}
struct A { int x; typedef int isA; };