Skip to content

Commit

Permalink
Show macro locations in format string for PR discussion only - DO NOT…
Browse files Browse the repository at this point in the history
… LAND
  • Loading branch information
mikecrowe committed Jul 21, 2024
1 parent 27c2a79 commit 3028e49
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 5 deletions.
55 changes: 50 additions & 5 deletions clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,18 +241,59 @@ FormatStringConverter::FormatStringConverter(
finalizeFormatText();
}

void debugLoc(const SourceLocation &TokenLoc, StringRef Name,
SourceManager &SM) {
llvm::dbgs() << "getImmediateExpansionRange for '" << Name << "': ";
SM.getImmediateExpansionRange(TokenLoc).getAsRange().print(llvm::dbgs(), SM);
llvm::dbgs() << "\n";

llvm::dbgs() << "getExpansionRange for '" << Name << "': ";
SM.getExpansionRange(TokenLoc).getAsRange().print(llvm::dbgs(), SM);
llvm::dbgs() << "\n";

llvm::dbgs() << "getTopMacroCaller for '" << Name << "': ";
SM.getTopMacroCallerLoc(TokenLoc).print(llvm::dbgs(), SM);
llvm::dbgs() << "\n";

llvm::dbgs() << "getImmediateMacroCallerLoc for '" << Name << "': ";
SM.getImmediateMacroCallerLoc(TokenLoc).print(llvm::dbgs(), SM);
llvm::dbgs() << "\n";

llvm::dbgs() << "getImmediateSpellingLoc for '" << Name << "': ";
SM.getImmediateSpellingLoc(TokenLoc).print(llvm::dbgs(), SM);
llvm::dbgs() << "\n";

llvm::dbgs() << "getFileLoc for '" << Name << "': ";
SM.getFileLoc(TokenLoc).print(llvm::dbgs(), SM);
llvm::dbgs() << "\n";

llvm::dbgs() << "\n";
}

std::optional<StringRef>
FormatStringConverter::formatStringContainsUnreplaceableMacro(
const CallExpr *Call, const StringLiteral *FormatExpr, SourceManager &SM,
Preprocessor &PP) {

SM.dump();

// If a macro invocation surrounds the entire call then we don't want that to
// inhibit conversion. The whole format string will appear to come from that
// macro, as will the function call.
std::optional<StringRef> MaybeSurroundingMacroName;
std::optional<FileID> MaybeSurroundingMacroFileID;
if (SourceLocation BeginCallLoc = Call->getBeginLoc();
BeginCallLoc.isMacroID())
BeginCallLoc.isMacroID()) {
MaybeSurroundingMacroName =
Lexer::getImmediateMacroName(BeginCallLoc, SM, PP.getLangOpts());
MaybeSurroundingMacroFileID = SM.getFileID(BeginCallLoc);

debugLoc(BeginCallLoc, "BeginCallLoc", SM);
}

// So that we don't need to return early and can show the TokenLoc location
// for every macro discovered in the format string.
std::optional<StringRef> Result;

for (auto I = FormatExpr->tokloc_begin(), E = FormatExpr->tokloc_end();
I != E; ++I) {
Expand All @@ -261,28 +302,32 @@ FormatStringConverter::formatStringContainsUnreplaceableMacro(
const StringRef MacroName =
Lexer::getImmediateMacroName(TokenLoc, SM, PP.getLangOpts());

if (SM.getFileID(TokenLoc) == MaybeSurroundingMacroFileID)
llvm::dbgs() << "TokenLoc has same FileID as call\n";
debugLoc(TokenLoc, MacroName, SM);

if (MaybeSurroundingMacroName != MacroName) {
// glibc uses __PRI64_PREFIX and __PRIPTR_PREFIX to define the prefixes
// for types that change size so we must look for multiple prefixes.
if (!MacroName.starts_with("PRI") && !MacroName.starts_with("__PRI"))
return MacroName;
Result = MacroName;

const SourceLocation TokenSpellingLoc = SM.getSpellingLoc(TokenLoc);
const OptionalFileEntryRef MaybeFileEntry =
SM.getFileEntryRefForID(SM.getFileID(TokenSpellingLoc));
if (!MaybeFileEntry)
return MacroName;
Result = MacroName;

HeaderSearch &HS = PP.getHeaderSearchInfo();
// Check if the file is a system header
if (!isSystem(HS.getFileDirFlavor(*MaybeFileEntry)) ||
llvm::sys::path::filename(MaybeFileEntry->getName()) !=
"inttypes.h")
return MacroName;
Result = MacroName;
}
}
}
return std::nullopt;
return Result;
}

void FormatStringConverter::emitAlignment(const PrintfSpecifier &FS,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %check_clang_tidy -check-suffixes=,STRICT \
// RUN: -std=c++23 %s modernize-use-std-print %t -- \
// RUN: -config="{CheckOptions: {StrictMode: true}}" \
// RUN: -- -isystem %clang_tidy_headers -fexceptions \
// RUN: -DPRI_CMDLINE_MACRO="\"s\"" \
// RUN: -D__PRI_CMDLINE_MACRO="\"s\""
#include <stdio.h>
#include <inttypes.h>

#define SURROUND_ALL(x) x
#define SURROUND_FORMAT_PARTIAL(x) x
#define FMT "s"

int main()
{
SURROUND_ALL(printf(SURROUND_FORMAT_PARTIAL("%" FMT) "\n", "42"));
}

0 comments on commit 3028e49

Please sign in to comment.