Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
clang-tools-extra/clangd/Preamble.cpp
Show First 20 Lines • Show All 207 Lines • ▼ Show 20 Lines | |||||
// Represents directives other than includes, where basic textual information is | // Represents directives other than includes, where basic textual information is | ||||
// enough. | // enough. | ||||
struct TextualPPDirective { | struct TextualPPDirective { | ||||
unsigned DirectiveLine; | unsigned DirectiveLine; | ||||
// Full text that's representing the directive, including the `#`. | // Full text that's representing the directive, including the `#`. | ||||
std::string Text; | std::string Text; | ||||
unsigned Offset; | unsigned Offset; | ||||
tok::PPKeywordKind Directive = tok::PPKeywordKind::pp_not_keyword; | |||||
sammccall: initialize to pp_unknown | |||||
// Name of the macro being defined in the case of a #define directive. | |||||
std::string MacroName; | |||||
bool operator==(const TextualPPDirective &RHS) const { | bool operator==(const TextualPPDirective &RHS) const { | ||||
return std::tie(DirectiveLine, Offset, Text) == | return std::tie(DirectiveLine, Offset, Text) == | ||||
std::tie(RHS.DirectiveLine, RHS.Offset, RHS.Text); | std::tie(RHS.DirectiveLine, RHS.Offset, RHS.Text); | ||||
} | } | ||||
}; | }; | ||||
// Formats a PP directive consisting of Prefix (e.g. "#define ") and Body ("X | // Formats a PP directive consisting of Prefix (e.g. "#define ") and Body ("X | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | struct DirectiveCollector : public PPCallbacks { | ||||
} | } | ||||
void MacroDefined(const Token &MacroNameTok, | void MacroDefined(const Token &MacroNameTok, | ||||
const MacroDirective *MD) override { | const MacroDirective *MD) override { | ||||
if (!InMainFile) | if (!InMainFile) | ||||
return; | return; | ||||
TextualDirectives.emplace_back(); | TextualDirectives.emplace_back(); | ||||
TextualPPDirective &TD = TextualDirectives.back(); | TextualPPDirective &TD = TextualDirectives.back(); | ||||
TD.Directive = tok::pp_define; | |||||
TD.MacroName = MacroNameTok.getIdentifierInfo()->getName().str(); | |||||
const auto *MI = MD->getMacroInfo(); | const auto *MI = MD->getMacroInfo(); | ||||
TD.Text = | TD.Text = | ||||
spellDirective("#define ", | spellDirective("#define ", | ||||
CharSourceRange::getTokenRange( | CharSourceRange::getTokenRange( | ||||
MI->getDefinitionLoc(), MI->getDefinitionEndLoc()), | MI->getDefinitionLoc(), MI->getDefinitionEndLoc()), | ||||
LangOpts, SM, TD.DirectiveLine, TD.Offset); | LangOpts, SM, TD.DirectiveLine, TD.Offset); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 261 Lines • ▼ Show 20 Lines | buildPreamble(PathRef FileName, CompilerInvocation CI, | ||||
if (Stats != nullptr) { | if (Stats != nullptr) { | ||||
Stats->TotalBuildTime = PreambleTimer.getTime(); | Stats->TotalBuildTime = PreambleTimer.getTime(); | ||||
Stats->FileSystemTime = TimedFS->getTime(); | Stats->FileSystemTime = TimedFS->getTime(); | ||||
Stats->SerializedSize = BuiltPreamble ? BuiltPreamble->getSize() : 0; | Stats->SerializedSize = BuiltPreamble ? BuiltPreamble->getSize() : 0; | ||||
} | } | ||||
if (BuiltPreamble) { | if (BuiltPreamble) { | ||||
log("Built preamble of size {0} for file {1} version {2} in {3} seconds", | log("Built preamble of size {0} for file {1} version {2} in {3} seconds", | ||||
BuiltPreamble->getSize(), FileName, Inputs.Version, | BuiltPreamble->getSize(), FileName, Inputs.Version, | ||||
PreambleTimer.getTime()); | PreambleTimer.getTime()); | ||||
std::vector<Diag> Diags = PreambleDiagnostics.take(); | std::vector<Diag> Diags = PreambleDiagnostics.take(); | ||||
auto Result = std::make_shared<PreambleData>(std::move(*BuiltPreamble)); | auto Result = std::make_shared<PreambleData>(std::move(*BuiltPreamble)); | ||||
Result->Version = Inputs.Version; | Result->Version = Inputs.Version; | ||||
Result->CompileCommand = Inputs.CompileCommand; | Result->CompileCommand = Inputs.CompileCommand; | ||||
Result->Diags = std::move(Diags); | Result->Diags = std::move(Diags); | ||||
Result->Includes = CapturedInfo.takeIncludes(); | Result->Includes = CapturedInfo.takeIncludes(); | ||||
Result->Pragmas = CapturedInfo.takePragmaIncludes(); | Result->Pragmas = CapturedInfo.takePragmaIncludes(); | ||||
Result->Macros = CapturedInfo.takeMacros(); | Result->Macros = CapturedInfo.takeMacros(); | ||||
▲ Show 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | if (DirectivesChanged) { | ||||
// If we've patched only the first directive, the macro definition would've | // If we've patched only the first directive, the macro definition would've | ||||
// been wrong for the rest of the file, since patch is applied after the | // been wrong for the rest of the file, since patch is applied after the | ||||
// baseline preamble. | // baseline preamble. | ||||
// | // | ||||
// Note that we deliberately ignore conditional directives and undefs to | // Note that we deliberately ignore conditional directives and undefs to | ||||
// reduce complexity. The former might cause problems because scanning is | // reduce complexity. The former might cause problems because scanning is | ||||
// imprecise and might pick directives from disabled regions. | // imprecise and might pick directives from disabled regions. | ||||
for (const auto &TD : ModifiedScan->TextualDirectives) { | for (const auto &TD : ModifiedScan->TextualDirectives) { | ||||
// Introduce an #undef directive before #defines to suppress any | |||||
// re-definition warnings. | |||||
if (TD.Directive == tok::pp_define) | |||||
i know we've discussed emitting all the #undef directives at the top of the patch together rather than right before #define directives. but i am failing to remember any benefits and looping twice here doesn't feel great. so leaving it as-is for now, LMK if it feels wrong. kadircet: i know we've discussed emitting all the `#undef` directives at the top of the patch together… | |||||
Patch << "#undef " << TD.MacroName << '\n'; | |||||
Patch << "#line " << TD.DirectiveLine << '\n'; | Patch << "#line " << TD.DirectiveLine << '\n'; | ||||
Patch << TD.Text << '\n'; | Patch << TD.Text << '\n'; | ||||
} | } | ||||
} | } | ||||
dlog("Created preamble patch: {0}", Patch.str()); | dlog("Created preamble patch: {0}", Patch.str()); | ||||
Patch.flush(); | Patch.flush(); | ||||
return PP; | return PP; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 66 Lines • Show Last 20 Lines |
initialize to pp_unknown