-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang][Sema] Combine fallout warnings to just one warning #127546
Conversation
@llvm/pr-subscribers-clang Author: None (foxtran) ChangesThis PR fixes Changes:
It looks like current tests does not check these cases properly. Full diff: https://github.com/llvm/llvm-project/pull/127546.diff 2 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f10af8f5bd6b2..4a7b33ebd01f4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -713,13 +713,13 @@ def err_thread_non_global : Error<
def err_thread_unsupported : Error<
"thread-local storage is not supported for the current target">;
-// FIXME: Combine fallout warnings to just one warning.
-def warn_maybe_falloff_nonvoid_function : Warning<
- "non-void function does not return a value in all control paths">,
- InGroup<ReturnType>;
-def warn_falloff_nonvoid_function : Warning<
- "non-void function does not return a value">,
+def warn_falloff_nonvoid : Warning<
+ "non-void %select{function|block|lambda|coroutine}0 "
+ "does not return a value%select{| in all control paths}1">,
InGroup<ReturnType>;
+def err_falloff_nonvoid : Error<
+ "non-void %select{function|block|lambda|coroutine}0 "
+ "does not return a value%select{| in all control paths}1">;
def warn_const_attr_with_pure_attr : Warning<
"'const' attribute imposes more restrictions; 'pure' attribute ignored">,
InGroup<IgnoredAttributes>;
@@ -727,16 +727,6 @@ def warn_pure_function_returns_void : Warning<
"'%select{pure|const}0' attribute on function returning 'void'; attribute ignored">,
InGroup<IgnoredAttributes>;
-def err_maybe_falloff_nonvoid_block : Error<
- "non-void block does not return a value in all control paths">;
-def err_falloff_nonvoid_block : Error<
- "non-void block does not return a value">;
-def warn_maybe_falloff_nonvoid_coroutine : Warning<
- "non-void coroutine does not return a value in all control paths">,
- InGroup<ReturnType>;
-def warn_falloff_nonvoid_coroutine : Warning<
- "non-void coroutine does not return a value">,
- InGroup<ReturnType>;
def warn_suggest_noreturn_function : Warning<
"%select{function|method}0 %1 could be declared with attribute 'noreturn'">,
InGroup<MissingNoreturn>, DefaultIgnore;
@@ -8408,12 +8398,6 @@ let CategoryName = "Lambda Issue" in {
"incomplete result type %0 in lambda expression">;
def err_noreturn_lambda_has_return_expr : Error<
"lambda declared 'noreturn' should not return">;
- def warn_maybe_falloff_nonvoid_lambda : Warning<
- "non-void lambda does not return a value in all control paths">,
- InGroup<ReturnType>;
- def warn_falloff_nonvoid_lambda : Warning<
- "non-void lambda does not return a value">,
- InGroup<ReturnType>;
def err_access_lambda_capture : Error<
// The ERRORs represent other special members that aren't constructors, in
// hopes that someone will bother noticing and reporting if they appear
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 589869d018657..ef527374b811f 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -544,25 +544,17 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
namespace {
struct CheckFallThroughDiagnostics {
- unsigned diag_MaybeFallThrough_HasNoReturn;
- unsigned diag_MaybeFallThrough_ReturnsNonVoid;
- unsigned diag_AlwaysFallThrough_HasNoReturn;
- unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
+ unsigned diag_FallThrough_HasNoReturn;
+ unsigned diag_FallThrough_ReturnsNonVoid;
unsigned diag_NeverFallThroughOrReturn;
- enum { Function, Block, Lambda, Coroutine } funMode;
+ enum { Function = 0, Block, Lambda, Coroutine } funMode;
SourceLocation FuncLoc;
static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
CheckFallThroughDiagnostics D;
D.FuncLoc = Func->getLocation();
- D.diag_MaybeFallThrough_HasNoReturn =
- diag::warn_falloff_noreturn_function;
- D.diag_MaybeFallThrough_ReturnsNonVoid =
- diag::warn_maybe_falloff_nonvoid_function;
- D.diag_AlwaysFallThrough_HasNoReturn =
- diag::warn_falloff_noreturn_function;
- D.diag_AlwaysFallThrough_ReturnsNonVoid =
- diag::warn_falloff_nonvoid_function;
+ D.diag_FallThrough_HasNoReturn = diag::warn_falloff_noreturn_function;
+ D.diag_FallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid;
// Don't suggest that virtual functions be marked "noreturn", since they
// might be overridden by non-noreturn functions.
@@ -576,8 +568,7 @@ struct CheckFallThroughDiagnostics {
isTemplateInstantiation = Function->isTemplateInstantiation();
if (!isVirtualMethod && !isTemplateInstantiation)
- D.diag_NeverFallThroughOrReturn =
- diag::warn_suggest_noreturn_function;
+ D.diag_NeverFallThroughOrReturn = diag::warn_suggest_noreturn_function;
else
D.diag_NeverFallThroughOrReturn = 0;
@@ -588,12 +579,8 @@ struct CheckFallThroughDiagnostics {
static CheckFallThroughDiagnostics MakeForCoroutine(const Decl *Func) {
CheckFallThroughDiagnostics D;
D.FuncLoc = Func->getLocation();
- D.diag_MaybeFallThrough_HasNoReturn = 0;
- D.diag_MaybeFallThrough_ReturnsNonVoid =
- diag::warn_maybe_falloff_nonvoid_coroutine;
- D.diag_AlwaysFallThrough_HasNoReturn = 0;
- D.diag_AlwaysFallThrough_ReturnsNonVoid =
- diag::warn_falloff_nonvoid_coroutine;
+ D.diag_FallThrough_HasNoReturn = 0;
+ D.diag_FallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid;
D.diag_NeverFallThroughOrReturn = 0;
D.funMode = Coroutine;
return D;
@@ -601,14 +588,8 @@ struct CheckFallThroughDiagnostics {
static CheckFallThroughDiagnostics MakeForBlock() {
CheckFallThroughDiagnostics D;
- D.diag_MaybeFallThrough_HasNoReturn =
- diag::err_noreturn_block_has_return_expr;
- D.diag_MaybeFallThrough_ReturnsNonVoid =
- diag::err_maybe_falloff_nonvoid_block;
- D.diag_AlwaysFallThrough_HasNoReturn =
- diag::err_noreturn_block_has_return_expr;
- D.diag_AlwaysFallThrough_ReturnsNonVoid =
- diag::err_falloff_nonvoid_block;
+ D.diag_FallThrough_HasNoReturn = diag::err_noreturn_block_has_return_expr;
+ D.diag_FallThrough_ReturnsNonVoid = diag::err_falloff_nonvoid;
D.diag_NeverFallThroughOrReturn = 0;
D.funMode = Block;
return D;
@@ -616,14 +597,8 @@ struct CheckFallThroughDiagnostics {
static CheckFallThroughDiagnostics MakeForLambda() {
CheckFallThroughDiagnostics D;
- D.diag_MaybeFallThrough_HasNoReturn =
- diag::err_noreturn_lambda_has_return_expr;
- D.diag_MaybeFallThrough_ReturnsNonVoid =
- diag::warn_maybe_falloff_nonvoid_lambda;
- D.diag_AlwaysFallThrough_HasNoReturn =
- diag::err_noreturn_lambda_has_return_expr;
- D.diag_AlwaysFallThrough_ReturnsNonVoid =
- diag::warn_falloff_nonvoid_lambda;
+ D.diag_FallThrough_HasNoReturn = diag::err_noreturn_lambda_has_return_expr;
+ D.diag_FallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid;
D.diag_NeverFallThroughOrReturn = 0;
D.funMode = Lambda;
return D;
@@ -633,8 +608,7 @@ struct CheckFallThroughDiagnostics {
bool HasNoReturn) const {
if (funMode == Function) {
return (ReturnsVoid ||
- D.isIgnored(diag::warn_maybe_falloff_nonvoid_function,
- FuncLoc)) &&
+ D.isIgnored(diag::warn_falloff_nonvoid, FuncLoc)) &&
(!HasNoReturn ||
D.isIgnored(diag::warn_noreturn_function_has_return_expr,
FuncLoc)) &&
@@ -643,9 +617,7 @@ struct CheckFallThroughDiagnostics {
}
if (funMode == Coroutine) {
return (ReturnsVoid ||
- D.isIgnored(diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||
- D.isIgnored(diag::warn_maybe_falloff_nonvoid_coroutine,
- FuncLoc)) &&
+ D.isIgnored(diag::warn_falloff_nonvoid, FuncLoc)) &&
(!HasNoReturn);
}
// For blocks / lambdas.
@@ -709,34 +681,34 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
// Either in a function body compound statement, or a function-try-block.
switch (CheckFallThrough(AC)) {
- case UnknownFallThrough:
- break;
+ case UnknownFallThrough:
+ break;
- case MaybeFallThrough:
- if (HasNoReturn)
- EmitDiag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
- else if (!ReturnsVoid)
- EmitDiag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
- break;
- case AlwaysFallThrough:
- if (HasNoReturn)
- EmitDiag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
- else if (!ReturnsVoid)
- EmitDiag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
- break;
- case NeverFallThroughOrReturn:
- if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
- } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
- S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
- } else {
- S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
- }
+ case MaybeFallThrough:
+ if (HasNoReturn)
+ EmitDiag(RBrace, CD.diag_FallThrough_HasNoReturn);
+ else if (!ReturnsVoid)
+ S.Diag(RBrace, CD.diag_FallThrough_ReturnsNonVoid) << CD.funMode << 1;
+ break;
+ case AlwaysFallThrough:
+ if (HasNoReturn)
+ EmitDiag(RBrace, CD.diag_FallThrough_HasNoReturn);
+ else if (!ReturnsVoid)
+ S.Diag(RBrace, CD.diag_FallThrough_ReturnsNonVoid) << CD.funMode << 0;
+ break;
+ case NeverFallThroughOrReturn:
+ if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
+ } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
+ } else {
+ S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
}
- break;
- case NeverFallThrough:
- break;
+ }
+ break;
+ case NeverFallThrough:
+ break;
}
}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, thanks for the cleanup. I’m doing something related to this at the moment and this definitely helps with that ;Þ
I think this might be a good candidate for the new %enum_select
thingy that @erichkeane added recently (see https://clang.llvm.org/docs/InternalsManual.html#formatting-a-diagnostic-argument for documentation if you’re not familiar w/ it).
Yep, thank you! Will it have redefinition problem since I need to share this enum between two diagnostics? |
Unfortunately, yes... llvm-project/clang/test/TableGen/select-enum-errors.td Lines 15 to 20 in 785a5b4
|
Hmm, that’s a good point. I think in that case, for now just use CC @AaronBallman @erichkeane Would it make sense to have proper support for reusing enums across diagnostics w/ |
That also reminds me: A while ago I ran into a bug where someone had added a few cases to one diagnotic but forgot to update another diagnostic that also needed those cases, and we ended up asserting because of that; if we require every diagnostic that uses |
Looks like I cannot have some variable with proper type generated from So, for
I can not find corresponding type to save enum values into specific container (expected |
Ah, that’s because it emits an anonymous enum inside a namespace; just use |
https://godbolt.org/z/4EjMGoqTn So, That is what I'd like to expect :D |
What we’re currently emitting is more or less (grep for namespace diag {
namespace FunModes {
enum {
Function,
// ...
};
}
} |
Yep, I checked #122505 |
806b166
to
973dde5
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
@Sirraide, CI should be happy now. I have merged |
Also, just a heads-up, #127623 is likely going to be merged soon and introduce some merge conflicts for you in (We generate an implicit |
#127623 has been merged. |
f216d8a
to
ccfa4c6
Compare
@Sirraide, I still do not see how to call EmitDiag with coroutines :) |
9696593
to
5ba28fc
Compare
466da73
to
5cf6684
Compare
Alright, that should really be everything at this point. Thanks! |
@Sirraide, thank you! |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/73/builds/13289 Here is the relevant piece of the build log for the reference
|
This PR fixes
FIXME: Combine fallout warnings to just one warning.
atDiagnosticssSemaKinds.td
.Changes:
warn_maybe_falloff_nonvoid_function
andwarn_falloff_nonvoid_function
,warn_maybe_falloff_nonvoid_coroutine
andwarn_falloff_nonvoid_coroutine
,warn_maybe_falloff_nonvoid_lambda
andwarn_falloff_nonvoid_lambda
were combined intowarn_falloff_nonvoid
,err_maybe_falloff_nonvoid_block
anderr_falloff_nonvoid_block
were combined intoerr_falloff_nonvoid
err_noreturn_block_has_return_expr
anderr_noreturn_lambda_has_return_expr
were merged intoerr_noreturn_has_return_expr
with the same semantics aswarn_falloff_nonvoid
orerr_falloff_nonvoid
.