Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/FileEntry.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Tooling/Inclusions/StandardLibrary.h"
Expand Down Expand Up @@ -157,8 +158,22 @@ headersForSpecialSymbol(const Symbol &S, const SourceManager &SM,
if (!ND)
return std::nullopt;
auto *II = ND->getIdentifier();
if (!II)
if (!II) {
// Special case global operator new/delete, these show up often enough in
// practice and stdlib mappings can't work with them as they're symbol-name
// based.
if (ND->getDeclContext()->isTranslationUnit()) {
switch (ND->getDeclName().getCXXOverloadedOperator()) {
case OverloadedOperatorKind::OO_New:
case OverloadedOperatorKind::OO_Delete:
return hintedHeadersForStdHeaders(
{tooling::stdlib::Header::named("<new>").value()}, SM, PI);
default:
break;
}
}
return std::nullopt;
}

// Check first for symbols that are part of our stdlib mapping. As we have
// header names for those.
Expand Down
45 changes: 45 additions & 0 deletions clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
#include "clang-include-cleaner/Analysis.h"
#include "clang-include-cleaner/Record.h"
#include "clang-include-cleaner/Types.h"
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/FileEntry.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Testing/TestAST.h"
#include "clang/Tooling/Inclusions/StandardLibrary.h"
Expand Down Expand Up @@ -617,6 +619,49 @@ TEST_F(HeadersForSymbolTest, AmbiguousStdSymbolsUsingShadow) {
Header(*tooling::stdlib::Header::named("<cstdio>"))));
}

TEST_F(HeadersForSymbolTest, GlobalOperatorNewDelete) {
Inputs.Code = R"cpp(
void k() {
int *x;
// make sure operator new/delete are part of TU.
x = static_cast<int*>(::operator new(sizeof(int)));
::operator delete(x);
}
)cpp";
buildAST();

// Find global new/delete operators.
struct Visitor : public DynamicRecursiveASTVisitor {
const NamedDecl *New = nullptr;
const NamedDecl *Delete = nullptr;
bool VisitNamedDecl(NamedDecl *ND) override {
if (!ND->getDeclContext()->isTranslationUnit())
return true;
switch (ND->getDeclName().getCXXOverloadedOperator()) {
case OO_New:
New = ND;
break;
case OO_Delete:
Delete = ND;
break;
default:
break;
}
return true;
}
};
Visitor V;
V.ShouldVisitImplicitCode = true;
V.TraverseDecl(AST->context().getTranslationUnitDecl());
ASSERT_TRUE(V.New) << "Couldn't find global new!";
ASSERT_TRUE(V.Delete) << "Couldn't find global delete!";
EXPECT_THAT(
headersForSymbol(*V.New, AST->sourceManager(), &PI),
UnorderedElementsAre(Header(*tooling::stdlib::Header::named("<new>"))));
EXPECT_THAT(
headersForSymbol(*V.Delete, AST->sourceManager(), &PI),
UnorderedElementsAre(Header(*tooling::stdlib::Header::named("<new>"))));
}

TEST_F(HeadersForSymbolTest, StandardHeaders) {
Inputs.Code = R"cpp(
Expand Down
Loading