[libclang] Fix annotation and getting a "macro expansion" cursor
for a builtin macro expansion.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139298 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h
index 7bcc962..e98a1ba 100644
--- a/include/clang/Lex/PreprocessingRecord.h
+++ b/include/clang/Lex/PreprocessingRecord.h
@@ -16,6 +16,7 @@
#include "clang/Lex/PPCallbacks.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Allocator.h"
#include <vector>
@@ -110,34 +111,6 @@
void operator delete(void* data) throw();
};
- /// \brief Records the location of a macro expansion.
- class MacroExpansion : public PreprocessedEntity {
- /// \brief The name of the macro being expanded.
- IdentifierInfo *Name;
-
- /// \brief The definition of this macro.
- MacroDefinition *Definition;
-
- public:
- MacroExpansion(IdentifierInfo *Name, SourceRange Range,
- MacroDefinition *Definition)
- : PreprocessedEntity(MacroExpansionKind, Range), Name(Name),
- Definition(Definition) { }
-
- /// \brief The name of the macro being expanded.
- IdentifierInfo *getName() const { return Name; }
-
- /// \brief The definition of the macro being expanded.
- MacroDefinition *getDefinition() const { return Definition; }
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const PreprocessedEntity *PE) {
- return PE->getKind() == MacroExpansionKind;
- }
- static bool classof(const MacroExpansion *) { return true; }
-
- };
-
/// \brief Records the presence of a preprocessor directive.
class PreprocessingDirective : public PreprocessedEntity {
public:
@@ -178,6 +151,44 @@
}
static bool classof(const MacroDefinition *) { return true; }
};
+
+ /// \brief Records the location of a macro expansion.
+ class MacroExpansion : public PreprocessedEntity {
+ /// \brief The definition of this macro or the name of the macro if it is
+ /// a builtin macro.
+ llvm::PointerUnion<IdentifierInfo *, MacroDefinition *> NameOrDef;
+
+ public:
+ MacroExpansion(IdentifierInfo *BuiltinName, SourceRange Range)
+ : PreprocessedEntity(MacroExpansionKind, Range),
+ NameOrDef(BuiltinName) { }
+
+ MacroExpansion(MacroDefinition *Definition, SourceRange Range)
+ : PreprocessedEntity(MacroExpansionKind, Range),
+ NameOrDef(Definition) { }
+
+ /// \brief True if it is a builtin macro.
+ bool isBuiltinMacro() const { return NameOrDef.is<IdentifierInfo *>(); }
+
+ /// \brief The name of the macro being expanded.
+ const IdentifierInfo *getName() const {
+ if (MacroDefinition *Def = getDefinition())
+ return Def->getName();
+ return NameOrDef.get<IdentifierInfo*>();
+ }
+
+ /// \brief The definition of the macro being expanded. May return null if
+ /// this is a builtin macro.
+ MacroDefinition *getDefinition() const {
+ return NameOrDef.dyn_cast<MacroDefinition *>();
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const PreprocessedEntity *PE) {
+ return PE->getKind() == MacroExpansionKind;
+ }
+ static bool classof(const MacroExpansion *) { return true; }
+ };
/// \brief Record the location of an inclusion directive, such as an
/// \c #include or \c #import statement.
diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp
index 6303c3d..d02db25 100644
--- a/lib/Lex/PreprocessingRecord.cpp
+++ b/lib/Lex/PreprocessingRecord.cpp
@@ -14,7 +14,6 @@
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Token.h"
-#include "clang/Basic/IdentifierTable.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Capacity.h"
@@ -113,10 +112,12 @@
if (!IncludeNestedMacroExpansions && Id.getLocation().isMacroID())
return;
- if (MacroDefinition *Def = findMacroDefinition(MI))
+ if (MI->isBuiltinMacro())
PreprocessedEntities.push_back(
- new (*this) MacroExpansion(Id.getIdentifierInfo(),
- Range, Def));
+ new (*this) MacroExpansion(Id.getIdentifierInfo(),Range));
+ else if (MacroDefinition *Def = findMacroDefinition(MI))
+ PreprocessedEntities.push_back(
+ new (*this) MacroExpansion(Def, Range));
}
void PreprocessingRecord::MacroDefined(const Token &Id,
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 251d0f6..e574e25 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1448,11 +1448,16 @@
if (PreprocessedEntity *PE = PPRec.getLoadedPreprocessedEntity(GlobalID-1))
return PE;
- MacroExpansion *ME =
- new (PPRec) MacroExpansion(getLocalIdentifier(F, Record[3]),
+ bool isBuiltin = Record[3];
+ MacroExpansion *ME;
+ if (isBuiltin)
+ ME = new (PPRec) MacroExpansion(getLocalIdentifier(F, Record[4]),
SourceRange(ReadSourceLocation(F, Record[1]),
- ReadSourceLocation(F, Record[2])),
- getLocalMacroDefinition(F, Record[4]));
+ ReadSourceLocation(F, Record[2])));
+ else
+ ME = new (PPRec) MacroExpansion(getLocalMacroDefinition(F, Record[4]),
+ SourceRange(ReadSourceLocation(F, Record[1]),
+ ReadSourceLocation(F, Record[2])));
PPRec.setLoadedPreallocatedEntity(GlobalID - 1, ME);
return ME;
}
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index bdca689..a995a70 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1871,8 +1871,11 @@
Record.push_back(NextPreprocessorEntityID);
AddSourceLocation(ME->getSourceRange().getBegin(), Record);
AddSourceLocation(ME->getSourceRange().getEnd(), Record);
- AddIdentifierRef(ME->getName(), Record);
- Record.push_back(getMacroDefinitionID(ME->getDefinition()));
+ Record.push_back(ME->isBuiltinMacro());
+ if (ME->isBuiltinMacro())
+ AddIdentifierRef(ME->getName(), Record);
+ else
+ Record.push_back(getMacroDefinitionID(ME->getDefinition()));
Stream.EmitRecord(PPD_MACRO_EXPANSION, Record);
continue;
}
diff --git a/test/Index/annotate-tokens-pp.c b/test/Index/annotate-tokens-pp.c
index a8ef8a7..1d06578 100644
--- a/test/Index/annotate-tokens-pp.c
+++ b/test/Index/annotate-tokens-pp.c
@@ -28,7 +28,9 @@
#include "pragma-once.h"
#include "guarded.h"
-// RUN: c-index-test -test-annotate-tokens=%s:2:1:30:1 -I%S/Inputs %s | FileCheck %s
+const char *fname = __FILE__;
+
+// RUN: c-index-test -test-annotate-tokens=%s:2:1:32:1 -I%S/Inputs %s | FileCheck %s
// CHECK: Punctuation: "#" [2:1 - 2:2] preprocessing directive=
// CHECK: Identifier: "define" [2:2 - 2:8] preprocessing directive=
// CHECK: Identifier: "STILL_NOTHING" [2:9 - 2:22] macro definition=STILL_NOTHING
@@ -189,3 +191,4 @@
// CHECK: Punctuation: "}" [26:1 - 26:2] UnexposedStmt=
// CHECK: {{28:1.*inclusion directive=pragma-once.h.*multi-include guarded}}
// CHECK: {{29:1.*inclusion directive=guarded.h.*multi-include guarded}}
+// CHECK: Identifier: "__FILE__" [31:21 - 31:29] macro expansion=__FILE__
diff --git a/test/Index/c-index-getCursor-pp.c b/test/Index/c-index-getCursor-pp.c
index df61ec0..0a10450 100644
--- a/test/Index/c-index-getCursor-pp.c
+++ b/test/Index/c-index-getCursor-pp.c
@@ -13,6 +13,8 @@
B(int x);
+const char *fname = __FILE__;
+
// RUN: c-index-test -cursor-at=%s:1:11 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-1 %s
// CHECK-1: macro definition=OBSCURE
// RUN: c-index-test -cursor-at=%s:2:14 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-2 %s
@@ -27,6 +29,8 @@
// CHECK-6: inclusion directive=a.h
// RUN: c-index-test -cursor-at=%s:14:1 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-7 %s
// CHECK-7: macro expansion=B:12:9
+// RUN: c-index-test -cursor-at=%s:16:25 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-8 %s
+// CHECK-8: macro expansion=__FILE__
// Same tests, but with "editing" optimizations
// RUN: env CINDEXTEST_EDITING=1 c-index-test -cursor-at=%s:1:11 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-1 %s