Skip to content

Commit

Permalink
[HIP] Defer operator overloading errors
Browse files Browse the repository at this point in the history
Although clang is able to defer overloading resolution
diagnostics for common functions. It does not defer
overloading resolution caused diagnostics for overloaded
operators.

This patch extends the existing deferred
diagnostic mechanism and defers a diagnostic caused
by overloaded operator.

Reviewed by: Artem Belevich

Differential Revision: https://reviews.llvm.org/D104505

Fixes: SWDEV-236370

Change-Id: I0ff9ef18f30820112182c5ff94ccba26c3b2b914
  • Loading branch information
yxsamliu authored and Subodh Gupta committed Jul 23, 2021
1 parent 023e918 commit f2943f6
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 6 deletions.
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -6648,7 +6648,7 @@ def warn_taking_address_of_packed_member : Warning<
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<
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Sema/Overload.h
Original file line number Diff line number Diff line change
Expand Up @@ -1051,9 +1051,6 @@ class Sema;

void destroyCandidates();

/// Whether diagnostics should be deferred.
bool shouldDeferDiags(Sema &S, ArrayRef<Expr *> Args, SourceLocation OpLoc);

public:
OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK,
OperatorRewriteInfo RewriteInfo = {})
Expand All @@ -1066,6 +1063,9 @@ class Sema;
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 =
Expand Down
16 changes: 16 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -1746,6 +1746,22 @@ class Sema final {
/// 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;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/Sema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1769,7 +1769,7 @@ Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID,
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;
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11641,7 +11641,8 @@ bool OverloadCandidateSet::shouldDeferDiags(Sema &S, ArrayRef<Expr *> Args,
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.size();
Expand Down Expand Up @@ -13809,6 +13810,8 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
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)
Expand Down
15 changes: 15 additions & 0 deletions clang/test/SemaCUDA/deferred-oeverload.cu
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
// 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.
Expand All @@ -31,12 +36,20 @@ __host__ void callee4(int); // com-note 2{{candidate function not viable: requir
__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'}}
}

Expand All @@ -45,6 +58,8 @@ __device__ void df() {
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; };
Expand Down

0 comments on commit f2943f6

Please sign in to comment.