Skip to content

Commit 889306b

Browse files
committed
[index] Add macro definitions to the index store
Add support for indexing macro definitions, undefs, and references in the index store. In the normal case of compiling source files the macros are indexed using preprocessor callbacks that include every reference. When we are instead indexing a module that has already been compiled (.pcm), we get the module macros from the preprocessor, and only one definition is found. Macro indexing is enabled by default, but can be disabled using a new -index-ignore-macros driver flag. rdar://47815401
1 parent ef78c5d commit 889306b

20 files changed

+314
-72
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,8 @@ def index_record_codegen_name : Flag<["-"], "index-record-codegen-name">, Flags<
620620
HelpText<"Record the codegen name for symbols">;
621621
def index_unit_output_path : Separate<["-"], "index-unit-output-path">, MetaVarName<"<path>">, Flags<[CC1Option]>,
622622
HelpText<"Use <path> as the output path for this compilation unit in the index unit file">;
623+
def index_ignore_macros : Flag<["-"], "index-ignore-macros">, Flags<[CC1Option]>,
624+
HelpText<"Ignore macros during indexing">;
623625

624626
// Make sure all other -ccc- options are rejected.
625627
def ccc_ : Joined<["-"], "ccc-">, Group<internal_Group>, Flags<[Unsupported]>;

clang/include/clang/Frontend/FrontendOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ class FrontendOptions {
302302

303303
unsigned IndexIgnoreSystemSymbols : 1;
304304
unsigned IndexRecordCodegenName : 1;
305+
unsigned IndexIgnoreMacros : 1;
305306

306307
/// Output (and read) PCM files regardless of compiler errors.
307308
unsigned AllowPCMWithCompilerErrors : 1;

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5098,6 +5098,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
50985098
Args.AddLastArg(CmdArgs, options::OPT_index_ignore_system_symbols);
50995099
Args.AddLastArg(CmdArgs, options::OPT_index_record_codegen_name);
51005100
Args.AddLastArg(CmdArgs, options::OPT_index_unit_output_path);
5101+
Args.AddLastArg(CmdArgs, options::OPT_index_ignore_macros);
51015102

51025103
// If '-o' is passed along with '-fsyntax-only' pass it along the cc1
51035104
// invocation so that the index action knows what the out file is.

clang/lib/Driver/ToolChains/Darwin.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
525525
Args.ClaimAllArgs(options::OPT_index_store_path);
526526
Args.ClaimAllArgs(options::OPT_index_ignore_system_symbols);
527527
Args.ClaimAllArgs(options::OPT_index_record_codegen_name);
528+
Args.ClaimAllArgs(options::OPT_index_ignore_macros);
528529

529530
/// Hack(tm) to ignore linking errors when we are doing ARC migration.
530531
if (Args.hasArg(options::OPT_ccc_arcmt_check,

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1894,6 +1894,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
18941894
Opts.IndexUnitOutputPath = std::string(Args.getLastArgValue(OPT_index_unit_output_path));
18951895
Opts.IndexIgnoreSystemSymbols = Args.hasArg(OPT_index_ignore_system_symbols);
18961896
Opts.IndexRecordCodegenName = Args.hasArg(OPT_index_record_codegen_name);
1897+
Opts.IndexIgnoreMacros = Args.hasArg(OPT_index_ignore_macros);
18971898

18981899
InputKind DashX(Language::Unknown);
18991900
if (const Arg *A = Args.getLastArg(OPT_x)) {

clang/lib/Index/ClangIndexRecordWriter.cpp

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ StringRef ClangIndexRecordWriter::getUSR(const Decl *D) {
2828
return Insert.first->second;
2929
}
3030

31+
StringRef ClangIndexRecordWriter::getUSR(const IdentifierInfo *Name,
32+
const MacroInfo *MI) {
33+
assert(Name && MI);
34+
auto Insert = USRByDecl.insert(std::make_pair(MI, StringRef()));
35+
if (Insert.second) {
36+
Insert.first->second = getUSRNonCached(Name, MI);
37+
}
38+
return Insert.first->second;
39+
}
40+
3141
StringRef ClangIndexRecordWriter::getUSRNonCached(const Decl *D) {
3242
SmallString<256> Buf;
3343
bool Ignore = generateUSRForDecl(D, Buf);
@@ -39,6 +49,19 @@ StringRef ClangIndexRecordWriter::getUSRNonCached(const Decl *D) {
3949
return StringRef(Ptr, USR.size());
4050
}
4151

52+
StringRef ClangIndexRecordWriter::getUSRNonCached(const IdentifierInfo *Name,
53+
const MacroInfo *MI) {
54+
SmallString<256> Buf;
55+
bool Ignore = generateUSRForMacro(Name->getName(), MI->getDefinitionLoc(),
56+
Ctx.getSourceManager(), Buf);
57+
if (Ignore)
58+
return StringRef();
59+
StringRef USR = Buf.str();
60+
char *Ptr = Allocator.Allocate<char>(USR.size());
61+
std::copy(USR.begin(), USR.end(), Ptr);
62+
return StringRef(Ptr, USR.size());
63+
}
64+
4265
ClangIndexRecordWriter::ClangIndexRecordWriter(ASTContext &Ctx,
4366
RecordingOptions Opts)
4467
: Impl(Opts.DataDirPath), Ctx(Ctx), RecordOpts(std::move(Opts)),
@@ -74,49 +97,63 @@ bool ClangIndexRecordWriter::writeRecord(StringRef Filename,
7497
return std::make_pair(LineNo, ColNo);
7598
};
7699

100+
llvm::DenseMap<const MacroInfo *, const IdentifierInfo *> MacroNames;
101+
77102
for (auto &Occur : IdxRecord.getDeclOccurrencesSortedByOffset()) {
78103
unsigned Line, Col;
79104
std::tie(Line, Col) = getLineCol(Occur.Offset);
80105
SmallVector<writer::SymbolRelation, 3> Related;
81106
Related.reserve(Occur.Relations.size());
82107
for (auto &Rel : Occur.Relations)
83108
Related.push_back(writer::SymbolRelation{Rel.RelatedSymbol, Rel.Roles});
109+
if (Occur.MacroName)
110+
MacroNames[Occur.DeclOrMacro.get<const MacroInfo *>()] = Occur.MacroName;
84111

85-
// FIXME: handle macro occurrence
86-
if (auto *D = Occur.DeclOrMacro.dyn_cast<const Decl *>())
87-
Impl.addOccurrence(D, Occur.Roles, Line, Col, Related);
112+
Impl.addOccurrence(Occur.DeclOrMacro.getOpaqueValue(), Occur.Roles, Line,
113+
Col, Related);
88114
}
89115

90116
PrintingPolicy Policy(Ctx.getLangOpts());
91117
Policy.SuppressTemplateArgsInCXXConstructors = true;
92118

93119
auto Result = Impl.endRecord(Error,
94120
[&](writer::OpaqueDecl OD, SmallVectorImpl<char> &Scratch) {
95-
const Decl *D = static_cast<const Decl *>(OD);
96-
auto Info = getSymbolInfo(D);
97-
98121
writer::Symbol Sym;
99-
Sym.SymInfo = Info;
100-
101-
auto *ND = dyn_cast<NamedDecl>(D);
102-
if (ND) {
103-
llvm::raw_svector_ostream OS(Scratch);
104-
DeclarationName DeclName = ND->getDeclName();
105-
if (!DeclName.isEmpty())
106-
DeclName.print(OS, Policy);
122+
auto DeclOrMacro =
123+
llvm::PointerUnion<const Decl *, const MacroInfo *>::getFromOpaqueValue(
124+
const_cast<void *>(OD));
125+
if (auto *MI = DeclOrMacro.dyn_cast<const MacroInfo *>()) {
126+
auto *II = MacroNames[MI];
127+
assert(II);
128+
Sym.SymInfo = getSymbolInfoForMacro(*MI);
129+
Sym.Name = II->getName();
130+
Sym.USR = getUSR(II, MI);
131+
assert(!Sym.USR.empty() && "Recorded macro without USR!");
132+
} else {
133+
const Decl *D = DeclOrMacro.get<const Decl *>();
134+
Sym.SymInfo = getSymbolInfo(D);
135+
136+
auto *ND = dyn_cast<NamedDecl>(D);
137+
if (ND) {
138+
llvm::raw_svector_ostream OS(Scratch);
139+
DeclarationName DeclName = ND->getDeclName();
140+
if (!DeclName.isEmpty())
141+
DeclName.print(OS, Policy);
142+
}
143+
unsigned NameLen = Scratch.size();
144+
Sym.Name = StringRef(Scratch.data(), NameLen);
145+
146+
Sym.USR = getUSR(D);
147+
assert(!Sym.USR.empty() && "Recorded decl without USR!");
148+
149+
if (ASTNameGen && ND) {
150+
llvm::raw_svector_ostream OS(Scratch);
151+
ASTNameGen->writeName(ND, OS);
152+
}
153+
unsigned CGNameLen = Scratch.size() - NameLen;
154+
Sym.CodeGenName = StringRef(Scratch.data() + NameLen, CGNameLen);
107155
}
108-
unsigned NameLen = Scratch.size();
109-
Sym.Name = StringRef(Scratch.data(), NameLen);
110156

111-
Sym.USR = getUSR(D);
112-
assert(!Sym.USR.empty() && "Recorded decl without USR!");
113-
114-
if (ASTNameGen && ND) {
115-
llvm::raw_svector_ostream OS(Scratch);
116-
ASTNameGen->writeName(ND, OS);
117-
}
118-
unsigned CGNameLen = Scratch.size() - NameLen;
119-
Sym.CodeGenName = StringRef(Scratch.data() + NameLen, CGNameLen);
120157
return Sym;
121158
});
122159

clang/lib/Index/ClangIndexRecordWriter.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
namespace clang {
2020
class ASTContext;
2121
class Decl;
22+
class IdentifierInfo;
23+
class MacroInfo;
2224

2325
namespace index {
2426
class FileIndexRecord;
@@ -31,7 +33,7 @@ class ClangIndexRecordWriter {
3133

3234
std::unique_ptr<ASTNameGenerator> ASTNameGen;
3335
llvm::BumpPtrAllocator Allocator;
34-
llvm::DenseMap<const Decl *, StringRef> USRByDecl;
36+
llvm::DenseMap<const void *, StringRef> USRByDecl;
3537
IndexRecordHasher Hasher;
3638

3739
public:
@@ -44,9 +46,11 @@ class ClangIndexRecordWriter {
4446
bool writeRecord(StringRef Filename, const FileIndexRecord &Record,
4547
std::string &Error, std::string *RecordFile = nullptr);
4648
StringRef getUSR(const Decl *D);
49+
StringRef getUSR(const IdentifierInfo *Name, const MacroInfo *MI);
4750

4851
private:
4952
StringRef getUSRNonCached(const Decl *D);
53+
StringRef getUSRNonCached(const IdentifierInfo *Name, const MacroInfo *MI);
5054
};
5155

5256
} // end namespace index

clang/lib/Index/IndexRecordHasher.cpp

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ using namespace llvm;
2626

2727
static hash_code computeHash(const TemplateArgument &Arg,
2828
IndexRecordHasher &Hasher);
29+
static hash_code hashLoc(const SourceManager &SM, SourceLocation Loc,
30+
bool IncludeOffset);
2931

3032
namespace {
3133
class DeclHashVisitor : public ConstDeclVisitor<DeclHashVisitor, hash_code> {
@@ -53,7 +55,8 @@ class DeclHashVisitor : public ConstDeclVisitor<DeclHashVisitor, hash_code> {
5355

5456
hash_code Hash = VisitDeclContext(D->getDeclContext());
5557
if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) {
56-
COMBINE_HASH(hashLoc(D->getLocation(), /*IncludeOffset=*/true));
58+
COMBINE_HASH(hashLoc(Hasher.getASTContext().getSourceManager(),
59+
D->getLocation(), /*IncludeOffset=*/true));
5760
} else
5861
COMBINE_HASH('a');
5962
return Hash;
@@ -127,30 +130,6 @@ class DeclHashVisitor : public ConstDeclVisitor<DeclHashVisitor, hash_code> {
127130
else
128131
return 0;
129132
}
130-
131-
hash_code hashLoc(SourceLocation Loc, bool IncludeOffset) {
132-
if (Loc.isInvalid()) {
133-
return 0;
134-
}
135-
hash_code Hash = INITIAL_HASH;
136-
const SourceManager &SM = Hasher.getASTContext().getSourceManager();
137-
Loc = SM.getFileLoc(Loc);
138-
const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc);
139-
const FileEntry *FE = SM.getFileEntryForID(Decomposed.first);
140-
if (FE) {
141-
COMBINE_HASH(llvm::sys::path::filename(FE->getName()));
142-
} else {
143-
// This case really isn't interesting.
144-
return 0;
145-
}
146-
if (IncludeOffset) {
147-
// Use the offest into the FileID to represent the location. Using
148-
// a line/column can cause us to look back at the original source file,
149-
// which is expensive.
150-
COMBINE_HASH(Decomposed.second);
151-
}
152-
return Hash;
153-
}
154133
};
155134
}
156135

@@ -160,6 +139,9 @@ hash_code IndexRecordHasher::hashRecord(const FileIndexRecord &Record) {
160139
COMBINE_HASH(Info.Roles, Info.Offset);
161140
if (auto *D = Info.DeclOrMacro.dyn_cast<const Decl *>()) {
162141
COMBINE_HASH(hash(D));
142+
} else {
143+
COMBINE_HASH(
144+
hash(Info.MacroName, Info.DeclOrMacro.get<const MacroInfo *>()));
163145
}
164146
for (auto &Rel : Info.Relations) {
165147
COMBINE_HASH(hash(Rel.RelatedSymbol));
@@ -168,6 +150,11 @@ hash_code IndexRecordHasher::hashRecord(const FileIndexRecord &Record) {
168150
return Hash;
169151
}
170152

153+
hash_code IndexRecordHasher::hash(const IdentifierInfo *Name,
154+
const MacroInfo *MI) {
155+
return tryCache(MI, MacroDef{Name, MI});
156+
}
157+
171158
hash_code IndexRecordHasher::hash(const Decl *D) {
172159
assert(D->isCanonicalDecl());
173160

@@ -304,6 +291,18 @@ static hash_code computeHash(const IdentifierInfo *II) {
304291
return hash_value(II->getName());
305292
}
306293

294+
hash_code IndexRecordHasher::hashImpl(MacroDef MD) {
295+
hash_code Hash = INITIAL_HASH;
296+
COMBINE_HASH(StringRef("@macro@"), computeHash(MD.Name));
297+
auto &SM = getASTContext().getSourceManager();
298+
auto Loc = MD.MI->getDefinitionLoc();
299+
// Only hash the location if it's not in a system header, to match how
300+
// USR generation behaves.
301+
if (Loc.isValid() && !SM.isInSystemHeader(Loc))
302+
COMBINE_HASH(hashLoc(SM, Loc, /*IncludeOffset=*/true));
303+
return Hash;
304+
}
305+
307306
static hash_code computeHash(Selector Sel) {
308307
unsigned N = Sel.getNumArgs();
309308
if (N == 0)
@@ -486,3 +485,27 @@ hash_code IndexRecordHasher::hashImpl(const NestedNameSpecifier *NNS) {
486485

487486
return Hash;
488487
}
488+
489+
static hash_code hashLoc(const SourceManager &SM, SourceLocation Loc,
490+
bool IncludeOffset) {
491+
if (Loc.isInvalid()) {
492+
return 0;
493+
}
494+
hash_code Hash = INITIAL_HASH;
495+
Loc = SM.getFileLoc(Loc);
496+
const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc);
497+
const FileEntry *FE = SM.getFileEntryForID(Decomposed.first);
498+
if (FE) {
499+
COMBINE_HASH(llvm::sys::path::filename(FE->getName()));
500+
} else {
501+
// This case really isn't interesting.
502+
return 0;
503+
}
504+
if (IncludeOffset) {
505+
// Use the offest into the FileID to represent the location. Using
506+
// a line/column can cause us to look back at the original source file,
507+
// which is expensive.
508+
COMBINE_HASH(Decomposed.second);
509+
}
510+
return Hash;
511+
}

clang/lib/Index/IndexRecordHasher.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ namespace clang {
1818
class ASTContext;
1919
class Decl;
2020
class DeclarationName;
21+
class IdentifierInfo;
22+
class MacroInfo;
2123
class NestedNameSpecifier;
2224
class QualType;
2325
class Type;
@@ -37,6 +39,7 @@ class IndexRecordHasher {
3739

3840
llvm::hash_code hashRecord(const FileIndexRecord &Record);
3941
llvm::hash_code hash(const Decl *D);
42+
llvm::hash_code hash(const IdentifierInfo *Name, const MacroInfo *M);
4043
llvm::hash_code hash(QualType Ty);
4144
llvm::hash_code hash(CanQualType Ty);
4245
llvm::hash_code hash(DeclarationName Name);
@@ -46,7 +49,13 @@ class IndexRecordHasher {
4649
template <typename T>
4750
llvm::hash_code tryCache(const void *Ptr, T Obj);
4851

52+
struct MacroDef {
53+
const IdentifierInfo *Name;
54+
const MacroInfo *MI;
55+
};
56+
4957
llvm::hash_code hashImpl(const Decl *D);
58+
llvm::hash_code hashImpl(MacroDef MD);
5059
llvm::hash_code hashImpl(CanQualType Ty);
5160
llvm::hash_code hashImpl(DeclarationName Name);
5261
llvm::hash_code hashImpl(const NestedNameSpecifier *NNS);

0 commit comments

Comments
 (0)