ziqingluo-90 updated this revision to Diff 517413.
ziqingluo-90 added a comment.
Move the traversal framework to `AnalysisBasedWarnings` so that the
`UnsafeBufferUsage` analyzer (as well as other possible analyzers) is still
function based. It is in the same pattern as the original `IssueWarnings`
function.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D146342/new/
https://reviews.llvm.org/D146342
Files:
clang/include/clang/Sema/AnalysisBasedWarnings.h
clang/lib/Sema/AnalysisBasedWarnings.cpp
clang/lib/Sema/Sema.cpp
clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
Index: clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
===================================================================
--- clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
+++ clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
@@ -226,11 +226,11 @@
void testTemplate(int * p) {
int *a[10];
foo(f(p, &p, a, a)[1]); // expected-warning{{unsafe buffer access}}
- // expected-note@-1{{in instantiation of function template specialization 'f<int *, 10>' requested here}}
+ // FIXME: expected note@-1{{in instantiation of function template specialization 'f<int *, 10>' requested here}}
const int **q = const_cast<const int **>(&p);
- testPointerArithmetic(p, q, p); //expected-note{{in instantiation of}}
+ testPointerArithmetic(p, q, p); //FIXME: expected note{{in instantiation of}}
}
void testPointerToMember() {
@@ -321,7 +321,7 @@
foo(ar[5]); // expected-note{{used in buffer access here}}
}
-template void fArr<int>(int t[]); // expected-note {{in instantiation of}}
+template void fArr<int>(int t[]); // FIXME: expected note {{in instantiation of}}
int testReturn(int t[]) {
// expected-warning@-1{{'t' is an unsafe pointer used for buffer access}}
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -1426,6 +1426,8 @@
}
}
+ AnalysisWarnings.IssueWarnings(Context.getTranslationUnitDecl());
+
// Check we've noticed that we're no longer parsing the initializer for every
// variable. If we miss cases, then at best we have a performance issue and
// at worst a rejects-valid bug.
Index: clang/lib/Sema/AnalysisBasedWarnings.cpp
===================================================================
--- clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -25,6 +25,7 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
#include "clang/Analysis/Analyses/CalledOnceCheck.h"
#include "clang/Analysis/Analyses/Consumed.h"
@@ -2290,6 +2291,90 @@
S.Diag(D.Loc, D.PD);
}
+void clang::sema::AnalysisBasedWarnings::IssueWarnings(
+ const TranslationUnitDecl *TU) {
+ if (!TU)
+ return; // This is unexpected, give up quietly.
+
+ DiagnosticsEngine &Diags = S.getDiagnostics();
+ const bool EmitFixits =
+ Diags.getDiagnosticOptions().ShowFixits && S.getLangOpts().CPlusPlus20;
+
+ if (S.hasUncompilableErrorOccurred() || Diags.getIgnoreAllWarnings())
+ // exit if having uncompilable errors or ignoring all warnings:
+ return;
+
+ // An AST Visitor that calls analyzers on each callable definition:
+ class CallableVisitor : public RecursiveASTVisitor<CallableVisitor> {
+ private:
+ Sema &S;
+ const bool EmitFixits;
+ // Will be set to true iff visiting a `LambdaExpr`:
+ bool IsVisitingLambda = false;
+
+ public:
+ CallableVisitor(Sema &S, bool EmitFixits) : S(S), EmitFixits(EmitFixits) {}
+
+ // The sole member function that clients of `CallableVisitor` should call:
+ void traverseTU(const TranslationUnitDecl *TU) {
+ for (auto I = TU->decls_begin(); I != TU->decls_end(); ++I)
+ TraverseDecl(*I);
+ }
+
+ bool TraverseDecl(Decl *Node) {
+ DiagnosticsEngine &Diags = S.getDiagnostics();
+
+ if (!Node)
+ return true;
+ // Do not do any analysis if we are going to just ignore them.
+ if (Diags.getSuppressSystemWarnings() &&
+ S.SourceMgr.isInSystemHeader(Node->getLocation()))
+ return true;
+ // To analyze callables:
+ if (isa<FunctionDecl, BlockDecl, ObjCMethodDecl>(Node) &&
+ Node->hasBody()) {
+ // For code in dependent contexts, we'll do this at instantiation time:
+ if (cast<DeclContext>(Node)->isDependentContext())
+ return true;
+
+ UnsafeBufferUsageReporter R(S);
+
+ checkUnsafeBufferUsage(Node, R, EmitFixits);
+ }
+ // Continue to traverse descendants:
+ return RecursiveASTVisitor::TraverseDecl(Node);
+ }
+
+ bool TraverseStmt(Stmt *Node, DataRecursionQueue *Queue = nullptr) {
+ if (!Node)
+ return true;
+ if (isa<LambdaExpr>(Node)) {
+ // to visit implicit children of `LambdaExpr`s:
+ IsVisitingLambda = true;
+
+ bool Result = RecursiveASTVisitor::TraverseStmt(Node);
+
+ IsVisitingLambda = false; // set the flag back
+ return Result;
+ }
+ return RecursiveASTVisitor::TraverseStmt(Node);
+ }
+
+ bool shouldVisitTemplateInstantiations() const { return true; }
+ bool shouldVisitImplicitCode() const {
+ // The function declaration representing a lambda is implicit and we want
+ // to visit it:
+ return IsVisitingLambda;
+ }
+ };
+
+ // Emit unsafe buffer usage warnings and fixits.
+ if (!Diags.isIgnored(diag::warn_unsafe_buffer_operation, SourceLocation()) ||
+ !Diags.isIgnored(diag::warn_unsafe_buffer_variable, SourceLocation())) {
+ CallableVisitor(S, EmitFixits).traverseTU(TU);
+ }
+}
+
void clang::sema::AnalysisBasedWarnings::IssueWarnings(
sema::AnalysisBasedWarnings::Policy P, sema::FunctionScopeInfo *fscope,
const Decl *D, QualType BlockType) {
@@ -2518,16 +2603,6 @@
if (S.getLangOpts().CPlusPlus && !fscope->isCoroutine() && isNoexcept(FD))
checkThrowInNonThrowingFunc(S, FD, AC);
- // Emit unsafe buffer usage warnings and fixits.
- if (!Diags.isIgnored(diag::warn_unsafe_buffer_operation, D->getBeginLoc()) ||
- !Diags.isIgnored(diag::warn_unsafe_buffer_variable, D->getBeginLoc())) {
- UnsafeBufferUsageReporter R(S);
- checkUnsafeBufferUsage(
- D, R,
- /*EmitFixits=*/S.getDiagnostics().getDiagnosticOptions().ShowFixits &&
- S.getLangOpts().CPlusPlus20);
- }
-
// If none of the previous checks caused a CFG build, trigger one here
// for the logical error handler.
if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
Index: clang/include/clang/Sema/AnalysisBasedWarnings.h
===================================================================
--- clang/include/clang/Sema/AnalysisBasedWarnings.h
+++ clang/include/clang/Sema/AnalysisBasedWarnings.h
@@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_SEMA_ANALYSISBASEDWARNINGS_H
#define LLVM_CLANG_SEMA_ANALYSISBASEDWARNINGS_H
+#include "clang/AST/Decl.h"
#include "llvm/ADT/DenseMap.h"
#include <memory>
@@ -95,6 +96,9 @@
void IssueWarnings(Policy P, FunctionScopeInfo *fscope,
const Decl *D, QualType BlockType);
+ // Issue warnings that require whole-translation-unit analysis.
+ void IssueWarnings(const TranslationUnitDecl *D);
+
Policy getDefaultPolicy() { return DefaultPolicy; }
void PrintStats() const;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits