Index: clang/lib/Sema/AnalysisBasedWarnings.cpp =================================================================== --- clang/lib/Sema/AnalysisBasedWarnings.cpp +++ clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -1140,6 +1140,10 @@ ++AnnotatedCnt; continue; // Fallthrough annotation, good. } + if (isFollowedByFallThroughComment(LastStmt)) { + ++AnnotatedCnt; + continue; // Fallthrough comment, good. + } if (!LastStmt) { // This block contains no executable statements. // Traverse its predecessors. @@ -1208,6 +1212,27 @@ return nullptr; } + bool isFollowedByFallThroughComment(const Stmt *stmt) const { + // Crude detection of whether the fallthough is marked by a comment like + // /*FALLTHOUGH*/ + bool Invalid; + const char *sourceData = + S.getSourceManager().getCharacterData(stmt->getEndLoc(), &Invalid); + if (Invalid) + return false; + const char *lineStart = strchr(sourceData, '\n'); + if (lineStart == nullptr) + return false; + ++lineStart; // start of next line + const char *lineEnd = strchr(lineStart, '\n'); + StringRef line(lineStart, + lineEnd ? lineEnd - lineStart : strlen(lineStart)); + llvm::Regex regex("(/\\*[ \\t]*fall[ -]?thr(ough|u)[ \\t]*\\*/)" + "|(//[ \\t]*fall[ -]?thr(ough|u)[ \\t]*)", + llvm::Regex::IgnoreCase); + return regex.match(line); + } + bool FoundSwitchStatements; AttrStmts FallthroughStmts; Sema &S; Index: clang/test/Sema/fallthrough-comment.c =================================================================== --- /dev/null +++ clang/test/Sema/fallthrough-comment.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c11 -verify -Wimplicit-fallthrough %s + +int fallthrough_comment(int n) { + switch (n) { + case 0: + n++; + // FALLTHROUGH + case 1: + n++; + /*fall-through*/ + case 2: + n++; + case 3: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '__attribute__((fallthrough));' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + n++; + break; + } + return n; +}