forked from OSchip/llvm-project
[AST] Fix potential nullptr dereference in Expr::HasSideEffects
Array returned by LambdaExpr::capture_inits() can contain nullptrs. Differential Revision: https://reviews.llvm.org/D83438
This commit is contained in:
parent
87f8a4f9a2
commit
fdb69539bc
|
@ -1931,6 +1931,7 @@ public:
|
|||
|
||||
/// Const iterator that walks over the capture initialization
|
||||
/// arguments.
|
||||
/// FIXME: This interface is prone to being used incorrectly.
|
||||
using const_capture_init_iterator = Expr *const *;
|
||||
|
||||
/// Retrieve the initialization expressions for this lambda's captures.
|
||||
|
|
|
@ -3629,7 +3629,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
|
|||
case LambdaExprClass: {
|
||||
const LambdaExpr *LE = cast<LambdaExpr>(this);
|
||||
for (Expr *E : LE->capture_inits())
|
||||
if (E->HasSideEffects(Ctx, IncludePossibleEffects))
|
||||
if (E && E->HasSideEffects(Ctx, IncludePossibleEffects))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ add_clang_unittest(ASTTests
|
|||
DeclTest.cpp
|
||||
EvaluateAsRValueTest.cpp
|
||||
ExternalASTSourceTest.cpp
|
||||
HasSideEffectsTest.cpp
|
||||
NamedDeclPrinterTest.cpp
|
||||
RecursiveASTVisitorTest.cpp
|
||||
SizelessTypesTest.cpp
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
//===- unittest/AST/HasSideEffectsTest.cpp --------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/Frontend/FrontendAction.h"
|
||||
#include "clang/Tooling/Tooling.h"
|
||||
#include "llvm/ADT/FunctionExtras.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <cassert>
|
||||
|
||||
using namespace clang;
|
||||
|
||||
namespace {
|
||||
class ProcessASTAction : public clang::ASTFrontendAction {
|
||||
public:
|
||||
ProcessASTAction(llvm::unique_function<void(clang::ASTContext &)> Process)
|
||||
: Process(std::move(Process)) {
|
||||
assert(this->Process);
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
|
||||
StringRef InFile) {
|
||||
class Consumer : public ASTConsumer {
|
||||
public:
|
||||
Consumer(llvm::function_ref<void(ASTContext &CTx)> Process)
|
||||
: Process(Process) {}
|
||||
|
||||
void HandleTranslationUnit(ASTContext &Ctx) override { Process(Ctx); }
|
||||
|
||||
private:
|
||||
llvm::function_ref<void(ASTContext &CTx)> Process;
|
||||
};
|
||||
|
||||
return std::make_unique<Consumer>(Process);
|
||||
}
|
||||
|
||||
private:
|
||||
llvm::unique_function<void(clang::ASTContext &)> Process;
|
||||
};
|
||||
|
||||
class RunHasSideEffects
|
||||
: public RecursiveASTVisitor<RunHasSideEffects> {
|
||||
public:
|
||||
RunHasSideEffects(ASTContext& Ctx)
|
||||
: Ctx(Ctx) {}
|
||||
|
||||
bool VisitLambdaExpr(LambdaExpr *LE) {
|
||||
LE->HasSideEffects(Ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
ASTContext& Ctx;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TEST(HasSideEffectsTest, All) {
|
||||
llvm::StringRef Code = R"cpp(
|
||||
void Test() {
|
||||
int msize = 4;
|
||||
float arr[msize];
|
||||
[&arr] {};
|
||||
}
|
||||
)cpp";
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
clang::tooling::runToolOnCode(
|
||||
std::make_unique<ProcessASTAction>(
|
||||
[&](clang::ASTContext &Ctx) {
|
||||
RunHasSideEffects Visitor(Ctx);
|
||||
Visitor.TraverseAST(Ctx);
|
||||
}
|
||||
),
|
||||
Code)
|
||||
);
|
||||
|
||||
}
|
Loading…
Reference in New Issue