Skip to content

Commit c3a93c1

Browse files
committed
Harmonize the various diagnostics.
This patch tries to follow the clang diagnostic style. Lexically we do not start with capital letter and do not end with punctuation. We provide some guarantees with asserts for that. In addition, we try to position the diagnostics in a better place by adding the source location range so that we get the carret diagnostic pointing to the right code.
1 parent 311b514 commit c3a93c1

31 files changed

Lines changed: 366 additions & 324 deletions

include/clad/Differentiator/BaseForwardModeVisitor.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,6 @@ class BaseForwardModeVisitor
9595
DifferentiateVarDecl(const clang::VarDecl* VD);
9696
virtual DeclDiff<clang::VarDecl>
9797
DifferentiateVarDecl(const clang::VarDecl* VD, bool ignoreInit);
98-
/// Shorthand for warning on differentiation of unsupported operators
99-
void unsupportedOpWarn(clang::SourceLocation loc,
100-
llvm::ArrayRef<llvm::StringRef> args = {}) {
101-
diag(clang::DiagnosticsEngine::Warning, loc,
102-
"attempt to differentiate unsupported operator, derivative \
103-
set to 0",
104-
args);
105-
}
10698
StmtDiff VisitCXXForRangeStmt(const clang::CXXForRangeStmt* FRS);
10799
StmtDiff VisitWhileStmt(const clang::WhileStmt* WS);
108100
StmtDiff VisitDoStmt(const clang::DoStmt* DS);

include/clad/Differentiator/CladUtils.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
#include "clang/AST/Type.h"
1414
#include "clang/Analysis/AnalysisDeclContext.h"
1515
#include "clang/Basic/Diagnostic.h"
16+
#include "clang/Basic/SourceLocation.h"
1617
#include "clang/Sema/Ownership.h"
1718
#include "clang/Sema/Sema.h"
1819
#include "llvm/ADT/StringRef.h"
1920

21+
#include <cassert>
2022
#include <string>
2123

2224
namespace clang {
@@ -49,16 +51,18 @@ namespace clad {
4951
clang::Stmt* initial,
5052
clang::Stmt* S);
5153

52-
/// Shorthand to issues a warning or error.
5354
template <std::size_t N>
54-
void EmitDiag(clang::Sema& semaRef,
55-
clang::DiagnosticsEngine::Level level, // Warning or Error
56-
clang::SourceLocation loc, const char (&format)[N],
57-
llvm::ArrayRef<llvm::StringRef> args = {}) {
58-
unsigned diagID = semaRef.Diags.getCustomDiagID(level, format);
59-
clang::Sema::SemaDiagnosticBuilder stream = semaRef.Diag(loc, diagID);
60-
for (auto arg : args)
61-
stream << arg;
55+
clang::Sema::SemaDiagnosticBuilder
56+
diag(clang::Sema& S, clang::DiagnosticsEngine::Level Level,
57+
clang::SourceLocation Loc, const char (&Format)[N]) {
58+
static_assert(N > 1, "Diagnostic format string must not be empty");
59+
assert(!std::isupper(Format[0]) && "Diagnostics start with lower case!");
60+
assert((std::isalpha(Format[N - 2]) || Format[N - 2] == ')' ||
61+
Format[N - 2] == '\'' || std::isdigit(Format[N - 2])) &&
62+
"Diagnostics end with no punctuation!");
63+
unsigned DiagID = S.Diags.getCustomDiagID(Level, Format);
64+
clang::Sema::SemaDiagnosticBuilder B = S.Diag(Loc, DiagID);
65+
return B;
6266
}
6367

6468
/// Creates nested name specifier associated with declaration context

include/clad/Differentiator/DerivativeBuilder.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@
99

1010
#include "Compatibility.h"
1111

12+
#include "clad/Differentiator/CladUtils.h"
1213
#include "clad/Differentiator/DerivedFnCollector.h"
1314
#include "clad/Differentiator/DiffPlanner.h"
1415

1516
#include "clang/AST/RecursiveASTVisitor.h"
1617
#include "clang/AST/StmtVisitor.h"
18+
#include "clang/Basic/Diagnostic.h"
1719
#include "clang/Sema/Sema.h"
1820

1921
#include <array>
@@ -126,14 +128,10 @@ namespace clad {
126128
llvm::MutableArrayRef<clang::Expr*> ARargs);
127129
/// Shorthand to issues a warning or error.
128130
template <std::size_t N>
129-
void diag(clang::DiagnosticsEngine::Level level, // Warning or Error
130-
clang::SourceLocation loc,
131-
const char (&format)[N],
132-
llvm::ArrayRef<llvm::StringRef> args = {}) {
133-
unsigned diagID = m_Sema.Diags.getCustomDiagID(level, format);
134-
clang::Sema::SemaDiagnosticBuilder stream = m_Sema.Diag(loc, diagID);
135-
for (auto arg : args)
136-
stream << arg;
131+
clang::Sema::SemaDiagnosticBuilder
132+
diag(clang::DiagnosticsEngine::Level Level, clang::SourceLocation Loc,
133+
const char (&Format)[N]) {
134+
return utils::diag(m_Sema, Level, Loc, Format);
137135
}
138136

139137
/// Lookup the result of finding a custom derivative or numerical

include/clad/Differentiator/ReverseModeVisitor.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include "clang/AST/ExprCXX.h"
2020
#include "clang/AST/RecursiveASTVisitor.h"
2121
#include "clang/AST/StmtVisitor.h"
22+
#include "clang/Basic/Diagnostic.h"
23+
#include "clang/Basic/SourceLocation.h"
2224
#include "clang/Sema/Sema.h"
2325

2426
#include <llvm/ADT/ArrayRef.h>
@@ -504,14 +506,6 @@ namespace clad {
504506
const clang::ParmVarDecl* param,
505507
llvm::SmallVectorImpl<clang::Stmt*>& PreCallStmts,
506508
bool isNonDiff, bool isCUDAKernel = false);
507-
/// Shorthand for warning on differentiation of unsupported operators
508-
void unsupportedOpWarn(clang::SourceLocation loc,
509-
llvm::ArrayRef<llvm::StringRef> args = {}) {
510-
diag(clang::DiagnosticsEngine::Warning,
511-
loc,
512-
"attempt to differentiate unsupported operator, ignored.",
513-
args);
514-
}
515509

516510
/// Allows to easily create and manage a counter for counting the number of
517511
/// executed iterations of a loop.

include/clad/Differentiator/VisitorBase.h

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
#include "DerivativeBuilder.h"
1212
#include "clad/Differentiator/CladUtils.h"
1313

14+
#include "clang/AST/Expr.h"
1415
#include "clang/AST/RecursiveASTVisitor.h"
1516
#include "clang/AST/StmtVisitor.h"
1617
#include "clang/AST/Type.h"
18+
#include "clang/Basic/Diagnostic.h"
1719
#include "clang/Basic/OperatorKinds.h"
1820
#include "clang/Sema/DeclSpec.h"
1921
#include "clang/Sema/Ownership.h"
@@ -25,6 +27,7 @@
2527
#include "llvm/Support/PrettyStackTrace.h"
2628

2729
#include <array>
30+
#include <cassert>
2831
#include <stack>
2932
#include <unordered_map>
3033

@@ -411,10 +414,39 @@ namespace clad {
411414
/// A flag for silencing warnings/errors output by diag function.
412415
/// Shorthand to issues a warning or error.
413416
template <std::size_t N>
414-
void diag(clang::DiagnosticsEngine::Level level, // Warning or Error
415-
clang::SourceLocation loc, const char (&format)[N],
416-
llvm::ArrayRef<llvm::StringRef> args = {}) {
417-
m_Builder.diag(level, loc, format, args);
417+
clang::Sema::SemaDiagnosticBuilder
418+
diag(clang::DiagnosticsEngine::Level level, clang::SourceLocation loc,
419+
const char (&format)[N]) {
420+
return m_Builder.diag(level, loc, format);
421+
}
422+
423+
void diagUnsupported(const clang::Decl* D) {
424+
clang::SourceLocation L = D->getBeginLoc();
425+
diag(clang::DiagnosticsEngine::Warning, L,
426+
"declaration kind '%0' is not supported")
427+
<< D->getDeclKindName() << L;
428+
}
429+
430+
void diagUnsupported(const clang::Stmt* S) {
431+
clang::SourceLocation L = S->getBeginLoc();
432+
diag(clang::DiagnosticsEngine::Warning, L,
433+
"statement kind '%0' is not supported")
434+
<< S->getStmtClassName() << L;
435+
}
436+
437+
void diagUnsupportedIndirectCalls(const clang::CallExpr* CE) {
438+
assert(!CE->getDirectCallee() && "This is a direct callee");
439+
clang::SourceLocation L = CE->getBeginLoc();
440+
diag(clang::DiagnosticsEngine::Warning, L,
441+
"differentiation of indirect calls is not supported")
442+
<< L;
443+
}
444+
445+
/// Shorthand for warning on differentiation of unsupported operators
446+
void unsupportedOpWarn(clang::SourceLocation loc) {
447+
diag(clang::DiagnosticsEngine::Warning, loc,
448+
"attempted to differentiate unsupported operator; treated as "
449+
"non-differentiable");
418450
}
419451

420452
/// Creates unique identifier of the form "_nameBase<number>" that is

lib/Differentiator/BaseForwardModeVisitor.cpp

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "ConstantFolder.h"
1010

1111
#include "clad/Differentiator/CladUtils.h"
12+
#include "clad/Differentiator/DerivativeBuilder.h"
1213
#include "clad/Differentiator/DiffMode.h"
1314
#include "clad/Differentiator/DiffPlanner.h"
1415
#include "clad/Differentiator/ErrorEstimator.h"
@@ -86,12 +87,11 @@ DerivativeAndOverload BaseForwardModeVisitor::Derive() {
8687
// or pointer type, only one of the indices have been requested
8788
if (DVI.size() > 1 || (isArrayOrPointerType(diffVarInfo.param->getType()) &&
8889
(diffVarInfo.paramIndexInterval.size() != 1))) {
89-
diag(DiagnosticsEngine::Error,
90-
m_DiffReq.Args ? m_DiffReq.Args->getEndLoc() : noLoc,
91-
"Forward mode differentiation w.r.t. several parameters at once is "
92-
"not "
93-
"supported, call 'clad::differentiate' for each parameter "
94-
"separately");
90+
SourceLocation L = m_DiffReq.Args ? m_DiffReq.Args->getBeginLoc() : noLoc;
91+
diag(DiagnosticsEngine::Error, L,
92+
"forward mode differentiation w.r.t. several parameters at once is "
93+
"not supported; call 'clad::differentiate' for each parameter")
94+
<< L;
9595
return {};
9696
}
9797

@@ -113,10 +113,11 @@ DerivativeAndOverload BaseForwardModeVisitor::Derive() {
113113
if (!m_IndependentVar->getType()
114114
->getPointeeOrArrayElementType()
115115
->isRealType()) {
116-
diag(DiagnosticsEngine::Error, m_IndependentVar->getEndLoc(),
117-
"attempted differentiation w.r.t. a parameter ('%0') which is not"
118-
" an array or pointer of a real type",
119-
{m_IndependentVar->getNameAsString()});
116+
SourceLocation L = m_IndependentVar->getBeginLoc();
117+
diag(DiagnosticsEngine::Error, L,
118+
"attempted differentiation w.r.t. parameter %0 which is not"
119+
" array or pointer of real type")
120+
<< m_IndependentVar << L;
120121
return {};
121122
}
122123
m_IndependentVarIndex = diffVarInfo.paramIndexInterval.Start;
@@ -130,10 +131,11 @@ DerivativeAndOverload BaseForwardModeVisitor::Derive() {
130131
isField = true;
131132
}
132133
if (!IsRealNonReferenceType(T)) {
133-
diag(DiagnosticsEngine::Error, m_DiffReq.Args->getEndLoc(),
134-
"Attempted differentiation w.r.t. %0 '%1' which is not "
135-
"of real type.",
136-
{(isField ? "member" : "parameter"), diffVarInfo.source});
134+
SourceLocation L = m_DiffReq.Args->getBeginLoc();
135+
diag(DiagnosticsEngine::Error, L,
136+
"attempted differentiation w.r.t. %select{member|parameter}0 '%1' "
137+
"which is not of real type")
138+
<< isField << diffVarInfo.source << L;
137139
return {};
138140
}
139141
}
@@ -338,11 +340,11 @@ void BaseForwardModeVisitor::GenerateSeeds(const clang::FunctionDecl* dFD) {
338340
// Produce an error.
339341
if (param != m_IndependentVar &&
340342
!utils::GetValueType(dParamType).isConstQualified()) {
341-
// FIXME: Use diagnostics style as in #1596
342-
diag(DiagnosticsEngine::Error, param->getLocation(),
343+
SourceLocation L = param->getLocation();
344+
diag(DiagnosticsEngine::Error, L,
343345
"dependent non-const pointer and array parameters "
344-
"are not supported; differentiate w.r.t. '%0' or mark it const",
345-
{param->getNameAsString()});
346+
"are not supported; differentiate w.r.t. %0 or mark it const")
347+
<< param << L;
346348
}
347349
continue;
348350
}
@@ -454,8 +456,7 @@ void BaseForwardModeVisitor::GenerateSeeds(const clang::FunctionDecl* dFD) {
454456
}
455457

456458
StmtDiff BaseForwardModeVisitor::VisitStmt(const Stmt* S) {
457-
diag(DiagnosticsEngine::Warning, S->getBeginLoc(),
458-
"attempted to differentiate unsupported statement, no changes applied");
459+
diagUnsupported(S);
459460
// Unknown stmt, just clone it.
460461
return StmtDiff(Clone(S));
461462
}
@@ -1012,8 +1013,7 @@ DiffMode BaseForwardModeVisitor::GetPushForwardMode() {
10121013
StmtDiff BaseForwardModeVisitor::VisitCallExpr(const CallExpr* CE) {
10131014
const FunctionDecl* FD = CE->getDirectCallee();
10141015
if (!FD) {
1015-
diag(DiagnosticsEngine::Warning, CE->getBeginLoc(),
1016-
"Differentiation of only direct calls is supported. Ignored");
1016+
diagUnsupportedIndirectCalls(CE);
10171017
return StmtDiff(Clone(CE));
10181018
}
10191019

@@ -1350,9 +1350,11 @@ BaseForwardModeVisitor::VisitBinaryOperator(const BinaryOperator* BinOp) {
13501350
(Ldiff.getExpr_dx()->isModifiableLvalue(m_Context) !=
13511351
Expr::MLV_Valid) &&
13521352
!isCladArrayType(Ldiff.getExpr_dx()->getType())) {
1353-
diag(DiagnosticsEngine::Warning, BinOp->getEndLoc(),
1353+
SourceLocation L = BinOp->getBeginLoc();
1354+
diag(DiagnosticsEngine::Warning, L,
13541355
"derivative of an assignment attempts to assign to unassignable "
1355-
"expr, assignment ignored");
1356+
"expr, assignment ignored")
1357+
<< L;
13561358
opDiff = ConstantFolder::synthesizeLiteral(m_Context.IntTy, m_Context, 0);
13571359
} else if (opCode == BO_Assign || opCode == BO_AddAssign ||
13581360
opCode == BO_SubAssign) {
@@ -1507,11 +1509,9 @@ StmtDiff BaseForwardModeVisitor::VisitDeclStmt(const DeclStmt* DS) {
15071509
if (typeDecl && (clad::utils::hasNonDifferentiableAttribute(typeDecl) ||
15081510
typeDecl->isLambda())) {
15091511
for (auto* D : DS->decls()) {
1510-
if (auto* VD = dyn_cast<VarDecl>(D))
1511-
decls.push_back(VD);
1512-
else
1513-
diag(DiagnosticsEngine::Warning, D->getEndLoc(),
1514-
"Unsupported declaration");
1512+
assert(isa<VarDecl>(D) && "Mixed decl types in a single decl stmt is "
1513+
"not standard c++ syntax");
1514+
decls.push_back(cast<VarDecl>(D));
15151515
}
15161516
Stmt* DSClone = BuildDeclStmt(decls);
15171517
return StmtDiff(DSClone, nullptr);
@@ -1556,8 +1556,7 @@ StmtDiff BaseForwardModeVisitor::VisitDeclStmt(const DeclStmt* DS) {
15561556
if (SADDiff.getDecl_dx())
15571557
declsDiff.push_back(SADDiff.getDecl_dx());
15581558
} else {
1559-
diag(DiagnosticsEngine::Warning, D->getEndLoc(),
1560-
"Unsupported declaration");
1559+
diagUnsupported(D);
15611560
}
15621561
}
15631562

@@ -1984,10 +1983,12 @@ BaseForwardModeVisitor::DeriveSwitchStmtBodyHelper(const Stmt* stmt,
19841983
// We can also solve this issue by creating new scope and compound
19851984
// statement block wherever they are required instead of enclosing all
19861985
// the statements of a case label in a single compound statement.
1987-
diag(DiagnosticsEngine::Error, containedSC->getBeginLoc(),
1988-
"Differentiating switch case label contained in a compound "
1986+
SourceLocation L = containedSC->getBeginLoc();
1987+
diag(DiagnosticsEngine::Error, L,
1988+
"differentiating switch case label contained in a compound "
19891989
"statement, other than the switch statement compound "
1990-
"statement, is not supported.");
1990+
"statement, is not supported")
1991+
<< L;
19911992
return activeSC;
19921993
}
19931994
}

lib/Differentiator/DerivativeBuilder.cpp

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -526,14 +526,12 @@ static void registerDerivative(Decl* D, Sema& S, const DiffRequest& R) {
526526
// functions or custom derivatives.
527527
if (!request.DeclarationOnly ||
528528
!(m_DFC.IsCladDerivative(FD) || m_DFC.IsCustomDerivative(FD))) {
529-
if (request.VerboseDiags)
530-
diag(DiagnosticsEngine::Error,
531-
request.CallContext ? request.CallContext->getBeginLoc()
532-
: noLoc,
533-
"attempted differentiation of function '%0', which does not "
534-
"have a "
535-
"definition",
536-
{FD->getNameAsString()});
529+
if (request.VerboseDiags) {
530+
SourceLocation L = request.CallContext->getBeginLoc();
531+
diag(DiagnosticsEngine::Error, L,
532+
"attempted differentiation of function %0, without definition")
533+
<< FD << L;
534+
}
537535
return {};
538536
}
539537
}
@@ -543,11 +541,11 @@ static void registerDerivative(Decl* D, Sema& S, const DiffRequest& R) {
543541

544542
// check if the function is non-differentiable.
545543
if (clad::utils::hasNonDifferentiableAttribute(FD)) {
546-
diag(DiagnosticsEngine::Error,
547-
request.CallContext ? request.CallContext->getBeginLoc() : noLoc,
548-
"attempted differentiation of function '%0', which is marked as "
549-
"non-differentiable",
550-
{FD->getNameAsString()});
544+
SourceLocation L = request.CallContext->getBeginLoc();
545+
diag(DiagnosticsEngine::Error, L,
546+
"attempted differentiation of function %0, which is marked as "
547+
"non-differentiable")
548+
<< FD;
551549
return {};
552550
}
553551

@@ -556,23 +554,21 @@ static void registerDerivative(Decl* D, Sema& S, const DiffRequest& R) {
556554
if (const CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(FD)) {
557555
const CXXRecordDecl* CD = MD->getParent();
558556
if (clad::utils::hasNonDifferentiableAttribute(CD)) {
559-
diag(DiagnosticsEngine::Error, MD->getLocation(),
560-
"attempted differentiation of method '%0' in class '%1', which "
561-
"is "
562-
"marked as "
563-
"non-differentiable",
564-
{MD->getNameAsString(), CD->getNameAsString()});
557+
SourceLocation L = MD->getLocation();
558+
diag(DiagnosticsEngine::Error, L,
559+
"attempted differentiation of method %0 in class %1, which "
560+
"is marked as non-differentiable")
561+
<< MD << CD << L;
565562
return {};
566563
}
567564
}
568565
} else if (const VarDecl* VD = request.Global) {
569566
// Warn the user about the usage of global variables.
570-
auto diagId = m_Sema.Diags.getCustomDiagID(
571-
DiagnosticsEngine::Warning,
572-
"The gradient utilizes a global variable '%0'"
573-
". Please make sure to properly reset '%0' before re-running "
574-
"the gradient.");
575-
m_Sema.Diag(VD->getLocation(), diagId) << VD->getName();
567+
SourceLocation L = VD->getLocation();
568+
diag(DiagnosticsEngine::Warning, L,
569+
"gradient uses a global variable %0; "
570+
"rerunning the gradient requires %0 to be reset")
571+
<< VD << L;
576572
}
577573

578574
DerivativeAndOverload result{};

0 commit comments

Comments
 (0)