aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang-c/Index.h13
-rw-r--r--include/clang/Frontend/ASTUnit.h10
-rw-r--r--include/clang/Frontend/PreprocessorOptions.h5
-rw-r--r--include/clang/Lex/PreprocessingRecord.h7
-rw-r--r--include/clang/Lex/Preprocessor.h2
-rw-r--r--lib/Frontend/ASTUnit.cpp14
-rw-r--r--lib/Frontend/CompilerInstance.cpp3
-rw-r--r--lib/Lex/PreprocessingRecord.cpp8
-rw-r--r--lib/Lex/Preprocessor.cpp5
-rw-r--r--lib/Serialization/ASTReader.cpp4
-rw-r--r--test/Index/nested-macro-instantiations.cpp20
-rw-r--r--tools/c-index-test/c-index-test.c23
-rw-r--r--tools/libclang/CIndex.cpp10
13 files changed, 98 insertions, 26 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 011999bfe9..97c0c7c0da 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -829,7 +829,18 @@ enum CXTranslationUnit_Flags {
* Note: this is a *temporary* option that is available only while
* we are testing C++ precompiled preamble support.
*/
- CXTranslationUnit_CXXChainedPCH = 0x20
+ CXTranslationUnit_CXXChainedPCH = 0x20,
+
+ /**
+ * \brief Used to indicate that the "detailed" preprocessing record,
+ * if requested, should also contain nested macro instantiations.
+ *
+ * Nested macro instantiations (i.e., macro instantiations that occur
+ * inside another macro instantiation) can, in some code bases, require
+ * a large amount of storage to due preprocessor metaprogramming. Moreover,
+ * its fairly rare that this information is useful for libclang clients.
+ */
+ CXTranslationUnit_NestedMacroInstantiations = 0x40
};
/**
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 57d9f712aa..339297eb93 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -249,6 +249,10 @@ private:
/// \brief Whether we should be caching code-completion results.
bool ShouldCacheCodeCompletionResults;
+ /// \brief Whether we want to include nested macro instantiations in the
+ /// detailed preprocessing record.
+ bool NestedMacroInstantiations;
+
static void ConfigureDiags(llvm::IntrusiveRefCntPtr<Diagnostic> &Diags,
const char **ArgBegin, const char **ArgEnd,
ASTUnit &AST, bool CaptureDiagnostics);
@@ -607,7 +611,8 @@ public:
bool CaptureDiagnostics = false,
bool PrecompilePreamble = false,
bool CompleteTranslationUnit = true,
- bool CacheCodeCompletionResults = false);
+ bool CacheCodeCompletionResults = false,
+ bool NestedMacroInstantiations = true);
/// LoadFromCommandLine - Create an ASTUnit from a vector of command line
/// arguments, which must specify exactly one source file.
@@ -636,7 +641,8 @@ public:
bool CompleteTranslationUnit = true,
bool CacheCodeCompletionResults = false,
bool CXXPrecompilePreamble = false,
- bool CXXChainedPCH = false);
+ bool CXXChainedPCH = false,
+ bool NestedMacroInstantiations = true);
/// \brief Reparse the source files using the same command-line options that
/// were originally used to produce this translation unit.
diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h
index e875ec1fef..e471c5cf1d 100644
--- a/include/clang/Frontend/PreprocessorOptions.h
+++ b/include/clang/Frontend/PreprocessorOptions.h
@@ -41,6 +41,10 @@ public:
/// record of all macro definitions and
/// instantiations.
+ /// \brief Whether the detailed preprocessing record includes nested macro
+ /// instantiations.
+ unsigned DetailedRecordIncludesNestedMacroInstantiations : 1;
+
/// The implicit PCH included at the start of the translation unit, or empty.
std::string ImplicitPCHInclude;
@@ -136,6 +140,7 @@ public:
public:
PreprocessorOptions() : UsePredefines(true), DetailedRecord(false),
+ DetailedRecordIncludesNestedMacroInstantiations(true),
DisablePCHValidation(false), DisableStatCache(false),
DumpDeserializedPCHDecls(false),
PrecompiledPreambleBytes(0, true),
diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h
index d1534496b3..e498e9d0a0 100644
--- a/include/clang/Lex/PreprocessingRecord.h
+++ b/include/clang/Lex/PreprocessingRecord.h
@@ -258,6 +258,10 @@ namespace clang {
/// including the various preprocessing directives processed, macros
/// instantiated, etc.
class PreprocessingRecord : public PPCallbacks {
+ /// \brief Whether we should include nested macro instantiations in
+ /// the preprocessing record.
+ bool IncludeNestedMacroInstantiations;
+
/// \brief Allocator used to store preprocessing objects.
llvm::BumpPtrAllocator BumpAlloc;
@@ -281,7 +285,8 @@ namespace clang {
void MaybeLoadPreallocatedEntities() const ;
public:
- PreprocessingRecord();
+ /// \brief Construct
+ explicit PreprocessingRecord(bool IncludeNestedMacroInstantiations);
/// \brief Allocate memory in the preprocessing record.
void *Allocate(unsigned Size, unsigned Align = 8) {
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 616507a914..817fab57d3 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -441,7 +441,7 @@ public:
/// \brief Create a new preprocessing record, which will keep track of
/// all macro expansions, macro definitions, etc.
- void createPreprocessingRecord();
+ void createPreprocessingRecord(bool IncludeNestedMacroInstantiations);
/// EnterMainSourceFile - Enter the specified FileID as the main source file,
/// which implicitly adds the builtin defines etc.
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 0d0fecdcf4..8827116f2e 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -102,6 +102,7 @@ ASTUnit::ASTUnit(bool _MainFileIsAST)
ConcurrencyCheckValue(CheckUnlocked),
PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0),
ShouldCacheCodeCompletionResults(false),
+ NestedMacroInstantiations(true),
CompletionCacheTopLevelHashValue(0),
PreambleTopLevelHashValue(0),
CurrentTopLevelHashValue(0),
@@ -927,6 +928,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
// If the main file has been overridden due to the use of a preamble,
// make that override happen and introduce the preamble.
PreprocessorOptions &PreprocessorOpts = Clang->getPreprocessorOpts();
+ PreprocessorOpts.DetailedRecordIncludesNestedMacroInstantiations
+ = NestedMacroInstantiations;
std::string PriorImplicitPCHInclude;
if (OverrideMainBuffer) {
PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
@@ -1712,7 +1715,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
bool CaptureDiagnostics,
bool PrecompilePreamble,
bool CompleteTranslationUnit,
- bool CacheCodeCompletionResults) {
+ bool CacheCodeCompletionResults,
+ bool NestedMacroInstantiations) {
// Create the AST unit.
llvm::OwningPtr<ASTUnit> AST;
AST.reset(new ASTUnit(false));
@@ -1723,6 +1727,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
AST->CompleteTranslationUnit = CompleteTranslationUnit;
AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
AST->Invocation = CI;
+ AST->NestedMacroInstantiations = NestedMacroInstantiations;
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
@@ -1747,7 +1752,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
bool CompleteTranslationUnit,
bool CacheCodeCompletionResults,
bool CXXPrecompilePreamble,
- bool CXXChainedPCH) {
+ bool CXXChainedPCH,
+ bool NestedMacroInstantiations) {
if (!Diags.getPtr()) {
// No diagnostics engine was provided, so create our own diagnostics object
// with the default options.
@@ -1814,6 +1820,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
AST->NumStoredDiagnosticsInPreamble = StoredDiagnostics.size();
AST->StoredDiagnostics.swap(StoredDiagnostics);
AST->Invocation = CI;
+ AST->NestedMacroInstantiations = NestedMacroInstantiations;
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
@@ -2265,6 +2272,9 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
PreprocessorOpts.PrecompiledPreambleBytes.second = false;
}
+ // Disable the preprocessing record
+ PreprocessorOpts.DetailedRecord = false;
+
llvm::OwningPtr<SyntaxOnlyAction> Act;
Act.reset(new SyntaxOnlyAction);
if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second,
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index ace3c5adb1..38fcfe3c47 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -227,7 +227,8 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags,
}
if (PPOpts.DetailedRecord)
- PP->createPreprocessingRecord();
+ PP->createPreprocessingRecord(
+ PPOpts.DetailedRecordIncludesNestedMacroInstantiations);
InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp
index 9555611dc5..0c8d948ce0 100644
--- a/lib/Lex/PreprocessingRecord.cpp
+++ b/lib/Lex/PreprocessingRecord.cpp
@@ -45,8 +45,9 @@ void PreprocessingRecord::MaybeLoadPreallocatedEntities() const {
ExternalSource->ReadPreprocessedEntities();
}
-PreprocessingRecord::PreprocessingRecord()
- : ExternalSource(0), NumPreallocatedEntities(0),
+PreprocessingRecord::PreprocessingRecord(bool IncludeNestedMacroInstantiations)
+ : IncludeNestedMacroInstantiations(IncludeNestedMacroInstantiations),
+ ExternalSource(0), NumPreallocatedEntities(0),
LoadedPreallocatedEntities(false)
{
}
@@ -120,6 +121,9 @@ MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
}
void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI) {
+ if (!IncludeNestedMacroInstantiations && Id.getLocation().isMacroID())
+ return;
+
if (MacroDefinition *Def = findMacroDefinition(MI))
PreprocessedEntities.push_back(
new (*this) MacroInstantiation(Id.getIdentifierInfo(),
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 31fd667a65..fdc18f8781 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -527,10 +527,11 @@ CommentHandler::~CommentHandler() { }
CodeCompletionHandler::~CodeCompletionHandler() { }
-void Preprocessor::createPreprocessingRecord() {
+void Preprocessor::createPreprocessingRecord(
+ bool IncludeNestedMacroInstantiations) {
if (Record)
return;
- Record = new PreprocessingRecord;
+ Record = new PreprocessingRecord(IncludeNestedMacroInstantiations);
addPPCallbacks(Record);
}
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index bad18ff02e..bdc46f590f 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2382,7 +2382,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
PP->getHeaderSearchInfo().SetExternalLookup(this);
if (TotalNumPreallocatedPreprocessingEntities > 0) {
if (!PP->getPreprocessingRecord())
- PP->createPreprocessingRecord();
+ PP->createPreprocessingRecord(true);
PP->getPreprocessingRecord()->SetExternalSource(*this,
TotalNumPreallocatedPreprocessingEntities);
}
@@ -2581,7 +2581,7 @@ void ASTReader::setPreprocessor(Preprocessor &pp) {
TotalNum += Chain[I]->NumPreallocatedPreprocessingEntities;
if (TotalNum) {
if (!PP->getPreprocessingRecord())
- PP->createPreprocessingRecord();
+ PP->createPreprocessingRecord(true);
PP->getPreprocessingRecord()->SetExternalSource(*this, TotalNum);
}
}
diff --git a/test/Index/nested-macro-instantiations.cpp b/test/Index/nested-macro-instantiations.cpp
new file mode 100644
index 0000000000..d0c9bbb1e7
--- /dev/null
+++ b/test/Index/nested-macro-instantiations.cpp
@@ -0,0 +1,20 @@
+#define FOO(x) x
+#define BAR(x) FOO(x)
+#define WIBBLE(x) BAR(x)
+
+WIBBLE(int x);
+
+// RUN: env CINDEXTEST_NESTED_MACROS=1 c-index-test -test-load-source all %s | FileCheck -check-prefix CHECK-WITH-NESTED %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_NESTED_MACROS=1 c-index-test -test-load-source all %s | FileCheck -check-prefix CHECK-WITH-NESTED %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_NESTED_MACROS=1 c-index-test -test-load-source-reparse 5 all %s | FileCheck -check-prefix CHECK-WITH-NESTED %s
+// CHECK-WITH-NESTED: nested-macro-instantiations.cpp:5:1: macro instantiation=WIBBLE:3:9 Extent=[5:1 - 5:7]
+// CHECK-WITH-NESTED: nested-macro-instantiations.cpp:3:19: macro instantiation=BAR:2:9 Extent=[3:19 - 5:14]
+// CHECK-WITH-NESTED: nested-macro-instantiations.cpp:2:16: macro instantiation=FOO:1:9 Extent=[2:16 - 5:14]
+// CHECK-WITH-NESTED: nested-macro-instantiations.cpp:5:1: VarDecl=x:5:1 (Definition) Extent=[5:1 - 5:14]
+
+// RUN: c-index-test -test-load-source all %s | FileCheck -check-prefix CHECK-WITHOUT-NESTED %s
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source all %s | FileCheck -check-prefix CHECK-WITHOUT-NESTED %s
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 all %s | FileCheck -check-prefix CHECK-WITHOUT-NESTED %s
+// CHECK-WITHOUT-NESTED: nested-macro-instantiations.cpp:5:1: macro instantiation=WIBBLE:3:9 Extent=[5:1 - 5:7]
+// CHECK-WITHOUT-NESTED-NOT: nested-macro-instantiations.cpp:3:19: macro instantiation=BAR:2:9 Extent=[3:19 - 5:14]
+// CHECK-WITHOUT-NESTED: nested-macro-instantiations.cpp:5:1: VarDecl=x:5:1 (Definition) Extent=[5:1 - 5:14]
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index e43ac0699f..a5d4909e63 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -37,6 +37,8 @@ static unsigned getDefaultParsingOptions() {
options |= clang_defaultEditingTranslationUnitOptions();
if (getenv("CINDEXTEST_COMPLETION_CACHING"))
options |= CXTranslationUnit_CacheCompletionResults;
+ if (getenv("CINDEXTEST_NESTED_MACROS"))
+ options |= CXTranslationUnit_NestedMacroInstantiations;
return options;
}
@@ -713,11 +715,11 @@ int perform_test_load_source(int argc, const char **argv,
return -1;
}
- TU = clang_createTranslationUnitFromSourceFile(Idx, 0,
- argc - num_unsaved_files,
- argv + num_unsaved_files,
- num_unsaved_files,
- unsaved_files);
+ TU = clang_parseTranslationUnit(Idx, 0,
+ argv + num_unsaved_files,
+ argc - num_unsaved_files,
+ unsaved_files, num_unsaved_files,
+ getDefaultParsingOptions());
if (!TU) {
fprintf(stderr, "Unable to load translation unit!\n");
free_remapped_files(unsaved_files, num_unsaved_files);
@@ -1231,11 +1233,12 @@ int perform_token_annotation(int argc, const char **argv) {
return -1;
CIdx = clang_createIndex(0, 1);
- TU = clang_createTranslationUnitFromSourceFile(CIdx, argv[argc - 1],
- argc - num_unsaved_files - 3,
- argv + num_unsaved_files + 2,
- num_unsaved_files,
- unsaved_files);
+ TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],
+ argv + num_unsaved_files + 2,
+ argc - num_unsaved_files - 3,
+ unsaved_files,
+ num_unsaved_files,
+ getDefaultParsingOptions());
if (!TU) {
fprintf(stderr, "unable to parse input\n");
clang_disposeIndex(CIdx);
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 7234da3f63..f17a415f44 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -2376,10 +2376,12 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
const char * const *command_line_args,
unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files) {
+ unsigned Options = CXTranslationUnit_DetailedPreprocessingRecord |
+ CXTranslationUnit_NestedMacroInstantiations;
return clang_parseTranslationUnit(CIdx, source_filename,
command_line_args, num_command_line_args,
unsaved_files, num_unsaved_files,
- CXTranslationUnit_DetailedPreprocessingRecord);
+ Options);
}
struct ParseTranslationUnitInfo {
@@ -2480,9 +2482,12 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
Args->push_back(source_filename);
// Do we need the detailed preprocessing record?
+ bool NestedMacroInstantiations = false;
if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
Args->push_back("-Xclang");
Args->push_back("-detailed-preprocessing-record");
+ NestedMacroInstantiations
+ = (options & CXTranslationUnit_NestedMacroInstantiations);
}
unsigned NumErrors = Diags->getClient()->getNumErrors();
@@ -2501,7 +2506,8 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
CompleteTranslationUnit,
CacheCodeCompetionResults,
CXXPrecompilePreamble,
- CXXChainedPCH));
+ CXXChainedPCH,
+ NestedMacroInstantiations));
if (NumErrors != Diags->getClient()->getNumErrors()) {
// Make sure to check that 'Unit' is non-NULL.