VERSION_CONTROL_BRANCH_REVISION = 21,
/// \brief Record code for the array of unused static functions.
- UNUSED_STATIC_FUNCS = 22
+ UNUSED_STATIC_FUNCS = 22,
+ /// \brief Record code for the table of offsets to macro definition
+ /// entries in the preprocessing record.
+ MACRO_DEFINITION_OFFSETS = 23
};
/// \brief Record types used within a source manager block.
/// \brief Describes one token.
/// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags]
- PP_TOKEN = 3
+ PP_TOKEN = 3,
+
+ /// \brief Describes a macro instantiation within the preprocessing
+ /// record.
+ PP_MACRO_INSTANTIATION = 4,
+
+ /// \brief Describes a macro definition within the preprocessing record.
+ PP_MACRO_DEFINITION = 5
};
/// \defgroup PCHAST Precompiled header AST constants
#include "clang/AST/Type.h"
#include "clang/AST/TemplateBase.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
+#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceManager.h"
class DeclContext;
class GotoStmt;
class LabelStmt;
+class MacroDefinition;
class NamedDecl;
class Preprocessor;
class Sema;
/// actually required will be de-serialized.
class PCHReader
: public ExternalPreprocessorSource,
+ public ExternalPreprocessingRecordSource,
public ExternalSemaSource,
public IdentifierInfoLookup,
public ExternalIdentifierLookup,
/// been loaded.
llvm::SmallVector<Selector, 16> SelectorsLoaded;
+ /// \brief Offsets of all of the macro definitions in the preprocessing
+ /// record in the PCH file.
+ const uint32_t *MacroDefinitionOffsets;
+
+ /// \brief The macro definitions we have already loaded.
+ llvm::SmallVector<MacroDefinition *, 16> MacroDefinitionsLoaded;
+
+ /// \brief The number of preallocated preprocessing entities in the
+ /// preprocessing record.
+ unsigned NumPreallocatedPreprocessingEntities;
+
/// \brief A sorted array of source ranges containing comments.
SourceRange *Comments;
}
/// \brief Set the Preprocessor to use.
- void setPreprocessor(Preprocessor &pp) {
- PP = &pp;
- }
+ void setPreprocessor(Preprocessor &pp);
/// \brief Sets and initializes the given Context.
void InitializeContext(ASTContext &Context);
/// which contains a (typically-empty) subset of the predefines
/// build prior to including the precompiled header.
const std::string &getSuggestedPredefines() { return SuggestedPredefines; }
+
+ /// \brief Read preprocessed entities into the
+ virtual void ReadPreprocessedEntities();
/// \brief Reads the source ranges that correspond to comments from
/// an external AST source.
/// \brief Read the set of macros defined by this external macro source.
virtual void ReadDefinedMacros();
+ /// \brief Retrieve the macro definition with the given ID.
+ MacroDefinition *getMacroDefinition(pch::IdentID ID);
+
/// \brief Retrieve the AST context that this PCH reader
/// supplements.
ASTContext *getContext() { return Context; }
class ASTContext;
class LabelStmt;
+class MacroDefinition;
class MemorizeStatCalls;
class Preprocessor;
class Sema;
/// defined.
llvm::DenseMap<const IdentifierInfo *, uint64_t> MacroOffsets;
+ /// \brief Mapping from macro definitions (as they occur in the preprocessing
+ /// record) to the index into the macro definitions table.
+ llvm::DenseMap<const MacroDefinition *, pch::IdentID> MacroDefinitions;
+
+ /// \brief Mapping from the macro definition indices in \c MacroDefinitions
+ /// to the corresponding offsets within the preprocessor block.
+ std::vector<uint32_t> MacroDefinitionOffsets;
+
/// \brief Declarations encountered that might be external
/// definitions.
///
return MacroOffsets[II];
}
+ /// \brief Retrieve the ID number corresponding to the given macro
+ /// definition.
+ pch::IdentID getMacroDefinitionID(MacroDefinition *MD);
+
/// \brief Emit a reference to a type.
void AddTypeRef(QualType T, RecordData &Record);
}
static bool classof(const MacroDefinition *) { return true; }
};
+
+ /// \brief An abstract class that should be subclassed by any external source
+ /// of preprocessing record entries.
+ class ExternalPreprocessingRecordSource {
+ public:
+ virtual ~ExternalPreprocessingRecordSource();
+ /// \brief Read any preallocated preprocessed entities from the external
+ /// source.
+ virtual void ReadPreprocessedEntities() = 0;
+ };
+
/// \brief A record of the steps taken while preprocessing a source file,
/// including the various preprocessing directives processed, macros
/// instantiated, etc.
/// \brief Mapping from MacroInfo structures to their definitions.
llvm::DenseMap<const MacroInfo *, MacroDefinition *> MacroDefinitions;
+ /// \brief External source of preprocessed entities.
+ ExternalPreprocessingRecordSource *ExternalSource;
+
+ /// \brief The number of preallocated entities (that are known to the
+ /// external source).
+ unsigned NumPreallocatedEntities;
+
+ /// \brief Whether we have already loaded all of the preallocated entities.
+ mutable bool LoadedPreallocatedEntities;
+
+ void MaybeLoadPreallocatedEntities() const ;
+
public:
+ PreprocessingRecord();
+
/// \brief Allocate memory in the preprocessing record.
void *Allocate(unsigned Size, unsigned Align = 8) {
return BumpAlloc.Allocate(Size, Align);
// Iteration over the preprocessed entities.
typedef std::vector<PreprocessedEntity *>::iterator iterator;
typedef std::vector<PreprocessedEntity *>::const_iterator const_iterator;
- iterator begin() { return PreprocessedEntities.begin(); }
- iterator end() { return PreprocessedEntities.end(); }
- const_iterator begin() const { return PreprocessedEntities.begin(); }
- const_iterator end() const { return PreprocessedEntities.end(); }
+ iterator begin(bool OnlyLocalEntities = false);
+ iterator end(bool OnlyLocalEntities = false);
+ const_iterator begin(bool OnlyLocalEntities = false) const;
+ const_iterator end(bool OnlyLocalEntities = false) const;
/// \brief Add a new preprocessed entity to this record.
void addPreprocessedEntity(PreprocessedEntity *Entity);
+ /// \brief Set the external source for preprocessed entities.
+ void SetExternalSource(ExternalPreprocessingRecordSource &Source,
+ unsigned NumPreallocatedEntities);
+
+ /// \brief Set the preallocated entry at the given index to the given
+ /// preprocessed entity.
+ void SetPreallocatedEntity(unsigned Index, PreprocessedEntity *Entity);
+
+ /// \brief Register a new macro definition.
+ void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinition *MD);
+
+ /// \brief Retrieve the preprocessed entity at the given index.
+ PreprocessedEntity *getPreprocessedEntity(unsigned Index) {
+ assert(Index < PreprocessedEntities.size() &&
+ "Out-of-bounds preprocessed entity");
+ return PreprocessedEntities[Index];
+ }
+
/// \brief Retrieve the macro definition that corresponds to the given
/// \c MacroInfo.
MacroDefinition *findMacroDefinition(MacroInfo *MI);
#include "clang/AST/Type.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Basic/OnDiskHashTable.h"
IdentifierOffsets(0),
MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
TotalSelectorsInMethodPool(0), SelectorOffsets(0),
- TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot),
- NumStatHits(0), NumStatMisses(0),
+ TotalNumSelectors(0), MacroDefinitionOffsets(0),
+ NumPreallocatedPreprocessingEntities(0), Comments(0), NumComments(0),
+ isysroot(isysroot), NumStatHits(0), NumStatMisses(0),
NumSLocEntriesRead(0), NumStatementsRead(0),
NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
IdentifierOffsets(0),
MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
TotalSelectorsInMethodPool(0), SelectorOffsets(0),
- TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot),
- NumStatHits(0), NumStatMisses(0),
+ TotalNumSelectors(0), MacroDefinitionOffsets(0),
+ NumPreallocatedPreprocessingEntities(0), Comments(0), NumComments(0),
+ isysroot(isysroot), NumStatHits(0), NumStatMisses(0),
NumSLocEntriesRead(0), NumStatementsRead(0),
NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
MacroInfo *MI = PP->AllocateMacroInfo(Loc);
MI->setIsUsed(isUsed);
+ unsigned NextIndex = 3;
if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
// Decode function-like macro info.
bool isC99VarArgs = Record[3];
bool isGNUVarArgs = Record[4];
MacroArgs.clear();
unsigned NumArgs = Record[5];
+ NextIndex = 6 + NumArgs;
for (unsigned i = 0; i != NumArgs; ++i)
MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
// Remember that we saw this macro last so that we add the tokens that
// form its body to it.
Macro = MI;
+
+ if (NextIndex + 1 == Record.size() && PP->getPreprocessingRecord()) {
+ // We have a macro definition. Load it now.
+ PP->getPreprocessingRecord()->RegisterMacroDefinition(Macro,
+ getMacroDefinition(Record[NextIndex]));
+ }
+
++NumMacrosRead;
break;
}
Macro->AddTokenToBody(Tok);
break;
}
+
+ case pch::PP_MACRO_INSTANTIATION: {
+ // If we already have a macro, that means that we've hit the end
+ // of the definition of the macro we were looking for. We're
+ // done.
+ if (Macro)
+ return;
+
+ if (!PP->getPreprocessingRecord()) {
+ Error("missing preprocessing record in PCH file");
+ return;
+ }
+
+ PreprocessingRecord &PPRec = *PP->getPreprocessingRecord();
+ if (PPRec.getPreprocessedEntity(Record[0]))
+ return;
+
+ MacroInstantiation *MI
+ = new (PPRec) MacroInstantiation(DecodeIdentifierInfo(Record[3]),
+ SourceRange(
+ SourceLocation::getFromRawEncoding(Record[1]),
+ SourceLocation::getFromRawEncoding(Record[2])),
+ getMacroDefinition(Record[4]));
+ PPRec.SetPreallocatedEntity(Record[0], MI);
+ return;
+ }
+
+ case pch::PP_MACRO_DEFINITION: {
+ // If we already have a macro, that means that we've hit the end
+ // of the definition of the macro we were looking for. We're
+ // done.
+ if (Macro)
+ return;
+
+ if (!PP->getPreprocessingRecord()) {
+ Error("missing preprocessing record in PCH file");
+ return;
+ }
+
+ PreprocessingRecord &PPRec = *PP->getPreprocessingRecord();
+ if (PPRec.getPreprocessedEntity(Record[0]))
+ return;
+
+ if (Record[1] >= MacroDefinitionsLoaded.size()) {
+ Error("out-of-bounds macro definition record");
+ return;
+ }
+
+ MacroDefinition *MD
+ = new (PPRec) MacroDefinition(DecodeIdentifierInfo(Record[4]),
+ SourceLocation::getFromRawEncoding(Record[5]),
+ SourceRange(
+ SourceLocation::getFromRawEncoding(Record[2]),
+ SourceLocation::getFromRawEncoding(Record[3])));
+ PPRec.SetPreallocatedEntity(Record[0], MD);
+ MacroDefinitionsLoaded[Record[1]] = MD;
+ return;
+ }
}
}
}
case pch::PP_MACRO_OBJECT_LIKE:
case pch::PP_MACRO_FUNCTION_LIKE:
- DecodeIdentifierInfo(Record[0]);
+ DecodeIdentifierInfo(Record[0]);
break;
case pch::PP_TOKEN:
// Ignore tokens.
break;
+
+ case pch::PP_MACRO_INSTANTIATION:
+ case pch::PP_MACRO_DEFINITION:
+ // Read the macro record.
+ ReadMacroRecord(Cursor.GetCurrentBitNo());
+ break;
}
}
}
+MacroDefinition *PCHReader::getMacroDefinition(pch::IdentID ID) {
+ if (ID == 0 || ID >= MacroDefinitionsLoaded.size())
+ return 0;
+
+ if (!MacroDefinitionsLoaded[ID])
+ ReadMacroRecord(MacroDefinitionOffsets[ID]);
+
+ return MacroDefinitionsLoaded[ID];
+}
+
/// \brief If we are loading a relocatable PCH file, and the filename is
/// not an absolute path, add the system root to the beginning of the file
/// name.
}
break;
}
+
+ case pch::MACRO_DEFINITION_OFFSETS:
+ MacroDefinitionOffsets = (const uint32_t *)BlobStart;
+ if (PP) {
+ if (!PP->getPreprocessingRecord())
+ PP->createPreprocessingRecord();
+ PP->getPreprocessingRecord()->SetExternalSource(*this, Record[0]);
+ } else {
+ NumPreallocatedPreprocessingEntities = Record[0];
+ }
+
+ MacroDefinitionsLoaded.resize(Record[1]);
+ break;
}
}
Error("premature end of bitstream in PCH file");
return Success;
}
+void PCHReader::setPreprocessor(Preprocessor &pp) {
+ PP = &pp;
+
+ if (NumPreallocatedPreprocessingEntities) {
+ if (!PP->getPreprocessingRecord())
+ PP->createPreprocessingRecord();
+ PP->getPreprocessingRecord()->SetExternalSource(*this,
+ NumPreallocatedPreprocessingEntities);
+ NumPreallocatedPreprocessingEntities = 0;
+ }
+}
+
void PCHReader::InitializeContext(ASTContext &Ctx) {
Context = &Ctx;
assert(Context && "Passed null context!");
return false;
}
+void PCHReader::ReadPreprocessedEntities() {
+ ReadDefinedMacros();
+}
+
void PCHReader::ReadComments(std::vector<SourceRange> &Comments) {
Comments.resize(NumComments);
std::copy(this->Comments, this->Comments + NumComments,
#include "clang/AST/Type.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Basic/FileManager.h"
RECORD(EXT_VECTOR_DECLS);
RECORD(COMMENT_RANGES);
RECORD(VERSION_CONTROL_BRANCH_REVISION);
-
+ RECORD(UNUSED_STATIC_FUNCS);
+ RECORD(MACRO_DEFINITION_OFFSETS);
+
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
RECORD(SM_SLOC_FILE_ENTRY);
RECORD(PP_MACRO_OBJECT_LIKE);
RECORD(PP_MACRO_FUNCTION_LIKE);
RECORD(PP_TOKEN);
-
+ RECORD(PP_MACRO_INSTANTIATION);
+ RECORD(PP_MACRO_DEFINITION);
+
// Decls and Types block.
BLOCK(DECLTYPES_BLOCK);
RECORD(TYPE_EXT_QUAL);
// Loop over all the macro definitions that are live at the end of the file,
// emitting each to the PP section.
+ PreprocessingRecord *PPRec = PP.getPreprocessingRecord();
for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
I != E; ++I) {
// FIXME: This emits macros in hash table order, we should do it in a stable
I != E; ++I)
AddIdentifierRef(*I, Record);
}
+
+ // If we have a detailed preprocessing record, record the macro definition
+ // ID that corresponds to this macro.
+ if (PPRec)
+ Record.push_back(getMacroDefinitionID(PPRec->findMacroDefinition(MI)));
+
Stream.EmitRecord(Code, Record);
Record.clear();
}
++NumMacros;
}
+
+ // If the preprocessor has a preprocessing record, emit it.
+ unsigned NumPreprocessingRecords = 0;
+ if (PPRec) {
+ for (PreprocessingRecord::iterator E = PPRec->begin(), EEnd = PPRec->end();
+ E != EEnd; ++E) {
+ Record.clear();
+
+ if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) {
+ Record.push_back(NumPreprocessingRecords++);
+ AddSourceLocation(MI->getSourceRange().getBegin(), Record);
+ AddSourceLocation(MI->getSourceRange().getEnd(), Record);
+ AddIdentifierRef(MI->getName(), Record);
+ Record.push_back(getMacroDefinitionID(MI->getDefinition()));
+ Stream.EmitRecord(pch::PP_MACRO_INSTANTIATION, Record);
+ continue;
+ }
+
+ if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
+ // Record this macro definition's location.
+ pch::IdentID ID = getMacroDefinitionID(MD);
+ if (ID != MacroDefinitionOffsets.size()) {
+ if (ID > MacroDefinitionOffsets.size())
+ MacroDefinitionOffsets.resize(ID + 1);
+
+ MacroDefinitionOffsets[ID] = Stream.GetCurrentBitNo();
+ } else
+ MacroDefinitionOffsets.push_back(Stream.GetCurrentBitNo());
+
+ Record.push_back(NumPreprocessingRecords++);
+ Record.push_back(ID);
+ AddSourceLocation(MD->getSourceRange().getBegin(), Record);
+ AddSourceLocation(MD->getSourceRange().getEnd(), Record);
+ AddIdentifierRef(MD->getName(), Record);
+ AddSourceLocation(MD->getLocation(), Record);
+ Stream.EmitRecord(pch::PP_MACRO_DEFINITION, Record);
+ continue;
+ }
+ }
+ }
+
Stream.ExitBlock();
+
+ // Write the offsets table for the preprocessing record.
+ if (NumPreprocessingRecords > 0) {
+ // Write the offsets table for identifier IDs.
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(pch::MACRO_DEFINITION_OFFSETS));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of records
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macro defs
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned MacroDefOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ Record.clear();
+ Record.push_back(pch::MACRO_DEFINITION_OFFSETS);
+ Record.push_back(NumPreprocessingRecords);
+ Record.push_back(MacroDefinitionOffsets.size());
+ Stream.EmitRecordWithBlob(MacroDefOffsetAbbrev, Record,
+ (const char *)&MacroDefinitionOffsets.front(),
+ MacroDefinitionOffsets.size() * sizeof(uint32_t));
+ }
}
void PCHWriter::WriteComments(ASTContext &Context) {
// Write the remaining PCH contents.
RecordData Record;
- Stream.EnterSubblock(pch::PCH_BLOCK_ID, 4);
+ Stream.EnterSubblock(pch::PCH_BLOCK_ID, 5);
WriteMetadata(Context, isysroot);
WriteLanguageOptions(Context.getLangOptions());
if (StatCalls && !isysroot)
return ID;
}
+pch::IdentID PCHWriter::getMacroDefinitionID(MacroDefinition *MD) {
+ if (MD == 0)
+ return 0;
+
+ pch::IdentID &ID = MacroDefinitions[MD];
+ if (ID == 0)
+ ID = MacroDefinitions.size();
+ return ID;
+}
+
void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {
if (SelRef.getAsOpaquePtr() == 0) {
Record.push_back(0);
using namespace clang;
+ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { }
+
+void PreprocessingRecord::MaybeLoadPreallocatedEntities() const {
+ if (!ExternalSource || LoadedPreallocatedEntities)
+ return;
+
+ LoadedPreallocatedEntities = true;
+ ExternalSource->ReadPreprocessedEntities();
+}
+
+PreprocessingRecord::PreprocessingRecord()
+ : ExternalSource(0), NumPreallocatedEntities(0),
+ LoadedPreallocatedEntities(false)
+{
+}
+
+PreprocessingRecord::iterator
+PreprocessingRecord::begin(bool OnlyLocalEntities) {
+ if (OnlyLocalEntities)
+ return PreprocessedEntities.begin() + NumPreallocatedEntities;
+
+ MaybeLoadPreallocatedEntities();
+ return PreprocessedEntities.begin();
+}
+
+PreprocessingRecord::iterator PreprocessingRecord::end(bool OnlyLocalEntities) {
+ if (!OnlyLocalEntities)
+ MaybeLoadPreallocatedEntities();
+
+ return PreprocessedEntities.end();
+}
+
+PreprocessingRecord::const_iterator
+PreprocessingRecord::begin(bool OnlyLocalEntities) const {
+ if (OnlyLocalEntities)
+ return PreprocessedEntities.begin() + NumPreallocatedEntities;
+
+ MaybeLoadPreallocatedEntities();
+ return PreprocessedEntities.begin();
+}
+
+PreprocessingRecord::const_iterator
+PreprocessingRecord::end(bool OnlyLocalEntities) const {
+ if (!OnlyLocalEntities)
+ MaybeLoadPreallocatedEntities();
+
+ return PreprocessedEntities.end();
+}
+
void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
PreprocessedEntities.push_back(Entity);
}
+void PreprocessingRecord::SetExternalSource(
+ ExternalPreprocessingRecordSource &Source,
+ unsigned NumPreallocatedEntities) {
+ assert(!ExternalSource &&
+ "Preprocessing record already has an external source");
+ ExternalSource = &Source;
+ this->NumPreallocatedEntities = NumPreallocatedEntities;
+ PreprocessedEntities.insert(PreprocessedEntities.begin(),
+ NumPreallocatedEntities, 0);
+}
+
+void PreprocessingRecord::SetPreallocatedEntity(unsigned Index,
+ PreprocessedEntity *Entity) {
+ assert(Index < NumPreallocatedEntities &&"Out-of-bounds preallocated entity");
+ PreprocessedEntities[Index] = Entity;
+}
+
+void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
+ MacroDefinition *MD) {
+ MacroDefinitions[Macro] = MD;
+}
+
MacroDefinition *PreprocessingRecord::findMacroDefinition(MacroInfo *MI) {
llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
= MacroDefinitions.find(MI);
MacroDefinitions[MI] = Def;
PreprocessedEntities.push_back(Def);
}
+
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fblocks -emit-pch -x objective-c %s -o %t.ast
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fblocks -emit-pch -x objective-c %s -detailed-preprocessing-record -o %t.ast
// RUN: c-index-test -test-file-scan %t.ast %s | FileCheck %s
@interface Foo
{
// CHECK: [52:33 - 52:36] DeclRefExpr=bee:45:8
// CHECK: [52:36 - 52:37] CallExpr=main:44:5
// CHECK: [52:37 - 53:2] UnexposedStmt=
+// CHECK: [55:9 - 55:26] macro definition=CONCAT
+// CHECK: [57:6 - 57:10] FunctionDecl=f:57:6 (Definition)
+// CHECK: [58:4 - 58:8] VarDecl=my_var:58:8 (Definition)
+// CHECK: [58:8 - 58:14] macro instantiation=CONCAT:55:9
CXSourceRange cxloc::translateSourceRange(const SourceManager &SM,
const LangOptions &LangOpts,
SourceRange R) {
- // FIXME: This is largely copy-paste from
- // TextDiagnosticPrinter::HighlightRange. When it is clear that this is what
- // we want the two routines should be refactored.
-
// We want the last character in this location, so we will adjust the
- // instantiation location accordingly.
-
- // If the location is from a macro instantiation, get the end of the
- // instantiation range.
+ // location accordingly.
+ // FIXME: How do do this with a macro instantiation location?
SourceLocation EndLoc = R.getEnd();
- SourceLocation InstLoc = SM.getInstantiationLoc(EndLoc);
- if (EndLoc.isMacroID())
- InstLoc = SM.getInstantiationRange(EndLoc).second;
-
- // Measure the length token we're pointing at, so we can adjust the physical
- // location in the file to point at the last character.
- //
- // FIXME: This won't cope with trigraphs or escaped newlines well. For that,
- // we actually need a preprocessor, which isn't currently available
- // here. Eventually, we'll switch the pointer data of
- // CXSourceLocation/CXSourceRange to a translation unit (CXXUnit), so that the
- // preprocessor will be available here. At that point, we can use
- // Preprocessor::getLocForEndOfToken().
- if (InstLoc.isValid()) {
- unsigned Length = Lexer::MeasureTokenLength(InstLoc, SM, LangOpts);
+ if (!EndLoc.isInvalid() && EndLoc.isFileID()) {
+ unsigned Length = Lexer::MeasureTokenLength(EndLoc, SM, LangOpts);
EndLoc = EndLoc.getFileLocWithOffset(Length);
}
= CXXUnit->getPreprocessor().getPreprocessingRecord()) {
// FIXME: Once we have the ability to deserialize a preprocessing record,
// do so.
- for (PreprocessingRecord::iterator E = PPRec->begin(),EEnd = PPRec->end();
+ bool OnlyLocalDecls
+ = !CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls();
+ for (PreprocessingRecord::iterator
+ E = PPRec->begin(OnlyLocalDecls),
+ EEnd = PPRec->end(OnlyLocalDecls);
E != EEnd; ++E) {
if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) {
if (Visit(MakeMacroInstantiationCursor(MI, CXXUnit)))