forked from OSchip/llvm-project
Revert '[analyzer][PlistMacroExpansion] Part 2.: Retrieving the macro name and primitive expansion'
llvm-svn: 346096
This commit is contained in:
parent
7430213d8e
commit
d96bdd2402
|
@ -16,7 +16,6 @@
|
|||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Basic/Version.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Lex/TokenConcatenation.h"
|
||||
#include "clang/Rewrite/Core/HTMLRewrite.h"
|
||||
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
|
||||
|
@ -401,6 +400,12 @@ void PlistPrinter::ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
|
|||
// Static function definitions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc,
|
||||
const Preprocessor &PP) {
|
||||
// TODO: Implement macro expansion.
|
||||
return { "", "" };
|
||||
}
|
||||
|
||||
/// Print coverage information to output stream {@code o}.
|
||||
/// May modify the used list of files {@code Fids} by inserting new ones.
|
||||
static void printCoverage(const PathDiagnostic *D,
|
||||
|
@ -716,196 +721,3 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
|
|||
// Finish.
|
||||
o << "</dict>\n</plist>";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Declarations of helper functions and data structures for expanding macros.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
struct MacroNameAndInfo {
|
||||
std::string Name;
|
||||
const MacroInfo *MI = nullptr;
|
||||
|
||||
MacroNameAndInfo(std::string N, const MacroInfo *MI)
|
||||
: Name(std::move(N)), MI(MI) {}
|
||||
};
|
||||
|
||||
/// Helper class for printing tokens.
|
||||
class TokenPrinter {
|
||||
llvm::raw_ostream &OS;
|
||||
const Preprocessor &PP;
|
||||
|
||||
Token PrevTok, PrevPrevTok;
|
||||
TokenConcatenation ConcatInfo;
|
||||
|
||||
public:
|
||||
TokenPrinter(llvm::raw_ostream &OS, const Preprocessor &PP)
|
||||
: OS(OS), PP(PP), ConcatInfo(PP) {
|
||||
PrevTok.setKind(tok::unknown);
|
||||
PrevPrevTok.setKind(tok::unknown);
|
||||
}
|
||||
|
||||
void printToken(const Token &Tok);
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer,
|
||||
SourceLocation MacroLoc,
|
||||
const Preprocessor &PP);
|
||||
|
||||
/// Retrieves the name of the macro and its MacroInfo.
|
||||
static MacroNameAndInfo getMacroNameAndInfo(SourceLocation ExpanLoc,
|
||||
const Preprocessor &PP);
|
||||
|
||||
/// Retrieves the ')' token that matches '(' \p It points to.
|
||||
static MacroInfo::tokens_iterator getMatchingRParen(
|
||||
MacroInfo::tokens_iterator It,
|
||||
MacroInfo::tokens_iterator End);
|
||||
|
||||
/// Retrieves the macro info for \p II refers to at \p Loc. This is important
|
||||
/// because macros can be redefined or undefined.
|
||||
static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP,
|
||||
const SourceManager &SM,
|
||||
const IdentifierInfo *II,
|
||||
SourceLocation Loc);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Definitions of helper functions and methods for expanding macros.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc,
|
||||
const Preprocessor &PP) {
|
||||
|
||||
llvm::SmallString<200> ExpansionBuf;
|
||||
llvm::raw_svector_ostream OS(ExpansionBuf);
|
||||
TokenPrinter Printer(OS, PP);
|
||||
return { getMacroNameAndPrintExpansion(Printer, MacroLoc, PP), OS.str() };
|
||||
}
|
||||
|
||||
static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer,
|
||||
SourceLocation MacroLoc,
|
||||
const Preprocessor &PP) {
|
||||
|
||||
const SourceManager &SM = PP.getSourceManager();
|
||||
|
||||
MacroNameAndInfo Info = getMacroNameAndInfo(SM.getExpansionLoc(MacroLoc), PP);
|
||||
const MacroInfo *MI = Info.MI;
|
||||
|
||||
// Iterate over the macro's tokens and stringify them.
|
||||
for (auto It = MI->tokens_begin(), E = MI->tokens_end(); It != E; ++It) {
|
||||
Token T = *It;
|
||||
|
||||
// If this token is not an identifier, we only need to print it.
|
||||
if (T.isNot(tok::identifier)) {
|
||||
Printer.printToken(T);
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto *II = T.getIdentifierInfo();
|
||||
assert(II &&
|
||||
"This token is an identifier but has no IdentifierInfo!");
|
||||
|
||||
// If this token is a macro that should be expanded inside the currect
|
||||
// macro.
|
||||
if (const MacroInfo *MI =
|
||||
getMacroInfoForLocation(PP, SM, II, T.getLocation())) {
|
||||
getMacroNameAndPrintExpansion(Printer, T.getLocation(), PP);
|
||||
|
||||
// If this is a function-like macro, skip its arguments, as
|
||||
// getExpandedMacro() already printed them. If this is the case, let's
|
||||
// first jumo to the '(' token.
|
||||
if (MI->getNumParams() != 0)
|
||||
It = getMatchingRParen(++It, E);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If control reached here, then this token isn't a macro identifier, print
|
||||
// it.
|
||||
Printer.printToken(T);
|
||||
}
|
||||
|
||||
return Info.Name;
|
||||
}
|
||||
|
||||
static MacroNameAndInfo getMacroNameAndInfo(SourceLocation ExpanLoc,
|
||||
const Preprocessor &PP) {
|
||||
|
||||
const SourceManager &SM = PP.getSourceManager();
|
||||
const LangOptions &LangOpts = PP.getLangOpts();
|
||||
|
||||
// First, we create a Lexer to lex *at the expansion location* the tokens
|
||||
// referring to the macro's name and its arguments.
|
||||
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(ExpanLoc);
|
||||
const llvm::MemoryBuffer *MB = SM.getBuffer(LocInfo.first);
|
||||
const char *MacroNameTokenPos = MB->getBufferStart() + LocInfo.second;
|
||||
|
||||
Lexer RawLexer(SM.getLocForStartOfFile(LocInfo.first), LangOpts,
|
||||
MB->getBufferStart(), MacroNameTokenPos, MB->getBufferEnd());
|
||||
|
||||
// Acquire the macro's name.
|
||||
Token TheTok;
|
||||
RawLexer.LexFromRawLexer(TheTok);
|
||||
|
||||
std::string MacroName = PP.getSpelling(TheTok);
|
||||
|
||||
const auto *II = PP.getIdentifierInfo(MacroName);
|
||||
assert(II && "Failed to acquire the IndetifierInfo for the macro!");
|
||||
|
||||
const MacroInfo *MI = getMacroInfoForLocation(PP, SM, II, ExpanLoc);
|
||||
assert(MI && "The macro must've been defined at it's expansion location!");
|
||||
|
||||
return { MacroName, MI };
|
||||
}
|
||||
|
||||
static MacroInfo::tokens_iterator getMatchingRParen(
|
||||
MacroInfo::tokens_iterator It,
|
||||
MacroInfo::tokens_iterator End) {
|
||||
|
||||
assert(It->is(tok::l_paren) && "This token should be '('!");
|
||||
|
||||
// Skip until we find the closing ')'.
|
||||
int ParanthesesDepth = 1;
|
||||
while (ParanthesesDepth != 0) {
|
||||
++It;
|
||||
|
||||
assert(It->isNot(tok::eof) &&
|
||||
"Encountered EOF while attempting to skip macro arguments!");
|
||||
assert(It != End &&
|
||||
"End of the macro definition reached before finding ')'!");
|
||||
|
||||
if (It->is(tok::l_paren))
|
||||
++ParanthesesDepth;
|
||||
|
||||
if (It->is(tok::r_paren))
|
||||
--ParanthesesDepth;
|
||||
}
|
||||
return It;
|
||||
}
|
||||
|
||||
static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP,
|
||||
const SourceManager &SM,
|
||||
const IdentifierInfo *II,
|
||||
SourceLocation Loc) {
|
||||
|
||||
const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II);
|
||||
if (!MD)
|
||||
return nullptr;
|
||||
|
||||
return MD->findDirectiveAtLoc(Loc, SM).getMacroInfo();
|
||||
}
|
||||
|
||||
void TokenPrinter::printToken(const Token &Tok) {
|
||||
// If the tokens were already space separated, or if they must be to avoid
|
||||
// them being implicitly pasted, add a space between them.
|
||||
// If this is the first token to be printed, don't print space.
|
||||
if (PrevTok.isNot(tok::unknown) && (Tok.hasLeadingSpace() ||
|
||||
ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok)))
|
||||
OS << ' ';
|
||||
|
||||
OS << PP.getSpelling(Tok);
|
||||
|
||||
PrevPrevTok = PrevTok;
|
||||
PrevTok = Tok;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -27,8 +27,8 @@ void nonFunctionLikeMacroTest() {
|
|||
*ptr = 5; // expected-warning{{Dereference of null pointer}}
|
||||
}
|
||||
|
||||
// CHECK: <key>name</key><string>SET_PTR_VAR_TO_NULL</string>
|
||||
// CHECK-NEXT: <key>expansion</key><string>ptr = 0</string>
|
||||
// CHECK: <key>name</key><string></string>
|
||||
// CHECK-NEXT: <key>expansion</key><string></string>
|
||||
|
||||
#define NULL 0
|
||||
#define SET_PTR_VAR_TO_NULL_WITH_NESTED_MACRO \
|
||||
|
@ -40,109 +40,5 @@ void nonFunctionLikeNestedMacroTest() {
|
|||
*ptr = 5; // expected-warning{{Dereference of null pointer}}
|
||||
}
|
||||
|
||||
// CHECK: <key>name</key><string>SET_PTR_VAR_TO_NULL_WITH_NESTED_MACRO</string>
|
||||
// CHECK-NEXT: <key>expansion</key><string>ptr =0</string>
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Tests for function-like macro expansions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void setToNull(int **vptr) {
|
||||
*vptr = nullptr;
|
||||
}
|
||||
|
||||
#define TO_NULL(x) \
|
||||
setToNull(x)
|
||||
|
||||
void functionLikeMacroTest() {
|
||||
int *ptr;
|
||||
TO_NULL(&ptr);
|
||||
*ptr = 5; // expected-warning{{Dereference of null pointer}}
|
||||
}
|
||||
|
||||
// TODO: Expand arguments.
|
||||
// CHECK: <key>name</key><string>TO_NULL</string>
|
||||
// CHECK: <key>expansion</key><string>setToNull(x)</string>
|
||||
|
||||
#define DOES_NOTHING(x) \
|
||||
{ \
|
||||
int b; \
|
||||
b = 5; \
|
||||
} \
|
||||
print(x)
|
||||
|
||||
#define DEREF(x) \
|
||||
DOES_NOTHING(x); \
|
||||
*x
|
||||
|
||||
void functionLikeNestedMacroTest() {
|
||||
int *a;
|
||||
TO_NULL(&a);
|
||||
DEREF(a) = 5; // expected-warning{{Dereference of null pointer}}
|
||||
}
|
||||
|
||||
// TODO: Expand arguments.
|
||||
// CHECK: <key>name</key><string>TO_NULL</string>
|
||||
// CHECK-NEXT: <key>expansion</key><string>setToNull(x)</string>
|
||||
|
||||
// TODO: Expand arguments.
|
||||
// CHECK: <key>name</key><string>DEREF</string>
|
||||
// CHECK-NEXT: <key>expansion</key><string>{ int b; b = 5; } print(x); *x</string>
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Tests for undefining and/or redifining macros.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define WILL_UNDEF_SET_NULL_TO_PTR(ptr) \
|
||||
ptr = nullptr;
|
||||
|
||||
void undefinedMacroByTheEndOfParsingTest() {
|
||||
int *ptr;
|
||||
WILL_UNDEF_SET_NULL_TO_PTR(ptr);
|
||||
*ptr = 5; // expected-warning{{Dereference of null pointer}}
|
||||
}
|
||||
|
||||
#undef WILL_UNDEF_SET_NULL_TO_PTR
|
||||
|
||||
// TODO: Expand arguments.
|
||||
// CHECK: <key>name</key><string>WILL_UNDEF_SET_NULL_TO_PTR</string>
|
||||
// CHECK-NEXT: <key>expansion</key><string>ptr = nullptr;</string>
|
||||
|
||||
#define WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr) \
|
||||
/* Nothing */
|
||||
#undef WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL
|
||||
#define WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr) \
|
||||
ptr = nullptr;
|
||||
|
||||
void macroRedefinedMultipleTimesTest() {
|
||||
int *ptr;
|
||||
WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr)
|
||||
*ptr = 5; // expected-warning{{Dereference of null pointer}}
|
||||
}
|
||||
|
||||
#undef WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL
|
||||
#define WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr) \
|
||||
print("This string shouldn't be in the plist file at all. Or anywhere, " \
|
||||
"but here.");
|
||||
|
||||
// TODO: Expand arguments.
|
||||
// CHECK: <key>name</key><string>WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL</string>
|
||||
// CHECK-NEXT: <key>expansion</key><string>ptr = nullptr;</string>
|
||||
|
||||
#define WILL_UNDEF_SET_NULL_TO_PTR_2(ptr) \
|
||||
ptr = nullptr;
|
||||
|
||||
#define PASS_PTR_TO_MACRO_THAT_WILL_BE_UNDEFD(ptr) \
|
||||
WILL_UNDEF_SET_NULL_TO_PTR_2(ptr)
|
||||
|
||||
void undefinedMacroInsideAnotherMacroTest() {
|
||||
int *ptr;
|
||||
PASS_PTR_TO_MACRO_THAT_WILL_BE_UNDEFD(ptr);
|
||||
*ptr = 5; // expected-warning{{Dereference of null pointer}}
|
||||
}
|
||||
|
||||
// TODO: Expand arguments.
|
||||
// CHECK: <key>name</key><string>PASS_PTR_TO_MACRO_THAT_WILL_BE_UNDEFD</string>
|
||||
// CHECK-NEXT: <key>expansion</key><string>ptr = nullptr;</string>
|
||||
|
||||
#undef WILL_UNDEF_SET_NULL_TO_PTR_2
|
||||
// CHECK: <key>name</key><string></string>
|
||||
// CHECK-NEXT: <key>expansion</key><string></string>
|
||||
|
|
Loading…
Reference in New Issue