From 3644d970095d9c638c658cfd17f8e19fc333aadc Mon Sep 17 00:00:00 2001
From: Douglas Gregor <dgregor@apple.com>
Date: Tue, 9 Oct 2012 16:01:50 +0000
Subject: [PATCH] If a macro has been #undef'd in a precompiled header, we
 still need to write out the macro history for that macro. Similarly, we need
 to cope with reading a macro definition that has been #undef'd.

Take advantage of this new ability so that global code-completion
results can refer to #undef'd macros, rather than losing them
entirely. For multiply defined/#undef'd macros, we will still get the
wrong result, but it's better than getting no result.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165502 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/IdentifierTable.h |  3 +++
 lib/Sema/SemaCodeComplete.cpp         | 26 ++++++++++++--------------
 lib/Serialization/ASTReader.cpp       |  2 ++
 lib/Serialization/ASTWriter.cpp       |  5 ++---
 test/Index/complete-macros.c          |  5 +++--
 5 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index b3b1842aadc..33a822dd099 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -147,6 +147,9 @@ public:
   bool hadMacroDefinition() const {
     return HadMacro;
   }
+  void setHadMacroDefinition(bool Val) {
+    HadMacro = Val;
+  }
 
   /// getTokenID - If this is a source-language token (e.g. 'for'), this API
   /// can be used to cause the lexer to map identifiers to source-language
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 74a4958d932..7d352d02600 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -2495,7 +2495,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
   }
   
   if (Kind == RK_Macro) {
-    MacroInfo *MI = PP.getMacroInfo(Macro);
+    MacroInfo *MI = PP.getMacroInfoHistory(Macro);
     assert(MI && "Not a macro?");
 
     Result.AddTypedTextChunk(
@@ -2902,6 +2902,7 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) {
 }
 
 static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
+                            bool IncludeUndefined,
                             bool TargetTypeIsPointer = false) {
   typedef CodeCompletionResult Result;
   
@@ -2910,11 +2911,8 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
   for (Preprocessor::macro_iterator M = PP.macro_begin(), 
                                  MEnd = PP.macro_end();
        M != MEnd; ++M) {
-    // FIXME: Eventually, we'd want to be able to look back to the macro
-    // definition that was actually active at the point of code completion (even
-    // if that macro has since been #undef'd).
-    if (M->first->hasMacroDefinition())
-      Results.AddResult(Result(M->first, 
+    if (IncludeUndefined || M->first->hasMacroDefinition())
+      Results.AddResult(Result(M->first,
                              getMacroUsagePriority(M->first->getName(),
                                                    PP.getLangOpts(),
                                                    TargetTypeIsPointer)));
@@ -3213,7 +3211,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
   }
   
   if (CodeCompleter->includeMacros())
-    AddMacroResults(PP, Results);
+    AddMacroResults(PP, Results, false);
   
   HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
                             Results.data(),Results.size());
@@ -3344,7 +3342,7 @@ void Sema::CodeCompleteExpression(Scope *S,
     AddPrettyFunctionResults(PP.getLangOpts(), Results);        
 
   if (CodeCompleter->includeMacros())
-    AddMacroResults(PP, Results, PreferredTypeIsPointer);
+    AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
   HandleCodeCompleteResults(this, CodeCompleter, 
                 CodeCompletionContext(CodeCompletionContext::CCC_Expression, 
                                       Data.PreferredType),
@@ -3736,7 +3734,7 @@ void Sema::CodeCompleteCase(Scope *S) {
   //so only say we include macros if the code completer says we do
   enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
   if (CodeCompleter->includeMacros()) {
-    AddMacroResults(PP, Results);
+    AddMacroResults(PP, Results, false);
     kind = CodeCompletionContext::CCC_OtherWithMacros;
   }
   
@@ -3959,7 +3957,7 @@ void Sema::CodeCompleteAfterIf(Scope *S) {
     AddPrettyFunctionResults(PP.getLangOpts(), Results);        
   
   if (CodeCompleter->includeMacros())
-    AddMacroResults(PP, Results);
+    AddMacroResults(PP, Results, false);
   
   HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
                             Results.data(),Results.size());
@@ -4960,7 +4958,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
                      CodeCompleter->includeGlobals());
   
   if (CodeCompleter->includeMacros())
-    AddMacroResults(PP, Results);
+    AddMacroResults(PP, Results, false);
 
   HandleCodeCompleteResults(this, CodeCompleter,
                             CodeCompletionContext::CCC_Type,
@@ -5190,7 +5188,7 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
   Results.ExitScope();
   
   if (CodeCompleter->includeMacros())
-    AddMacroResults(PP, Results);
+    AddMacroResults(PP, Results, false);
   HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
                             Results.data(), Results.size());
   
@@ -7190,7 +7188,7 @@ void Sema::CodeCompletePreprocessorExpression() {
                         CodeCompletionContext::CCC_PreprocessorExpression);
   
   if (!CodeCompleter || CodeCompleter->includeMacros())
-    AddMacroResults(PP, Results);
+    AddMacroResults(PP, Results, true);
   
     // defined (<macro>)
   Results.EnterNewScope();
@@ -7239,7 +7237,7 @@ void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
   }
   
   if (!CodeCompleter || CodeCompleter->includeMacros())
-    AddMacroResults(PP, Builder);
+    AddMacroResults(PP, Builder, true);
   
   Results.clear();
   Results.insert(Results.end(), 
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index ff418caf9ef..05a453143c7 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1460,6 +1460,8 @@ void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ModuleFile &F,
   if (Visible) {
     // Note that this identifier has a macro definition.
     II->setHasMacroDefinition(true);
+  } else {
+    II->setHadMacroDefinition(true);
   }
   
   // Adjust the offset to a global offset.
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index b8a0c28938f..19a236fde2f 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1698,14 +1698,13 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
     IdentifierInfo *Name
       = const_cast<IdentifierInfo *>(DeserializedMacroNames[I]);
     if (Name->hadMacroDefinition() && MacroDefinitionsSeen.insert(Name))
-      MacrosToEmit.push_back(std::make_pair(Name, PP.getMacroInfo(Name)));
+      MacrosToEmit.push_back(std::make_pair(Name,
+                                            PP.getMacroInfoHistory(Name)));
   }
 
   for (unsigned I = 0, N = MacrosToEmit.size(); I != N; ++I) {
     const IdentifierInfo *Name = MacrosToEmit[I].first;
     MacroInfo *MI = MacrosToEmit[I].second;
-    if (!MI)
-      continue;
 
     // History of macro definitions for this identifier in chronological order.
     SmallVector<MacroInfo*, 8> MacroHistory;
diff --git a/test/Index/complete-macros.c b/test/Index/complete-macros.c
index df798a8477f..6d27b449ae2 100644
--- a/test/Index/complete-macros.c
+++ b/test/Index/complete-macros.c
@@ -1,8 +1,8 @@
 // Note: the run lines follow their respective tests, since line/column
 // matter in this test.
-
 #define FOO(Arg1,Arg2) foobar
 #define nil 0
+#undef FOO
 void f() {
 
 }
@@ -25,7 +25,8 @@ void test_variadic() {
   
 }
 
-// RUN: c-index-test -code-completion-at=%s:7:1 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: c-index-test -code-completion-at=%s:7:1 %s | FileCheck -check-prefix=CHECK-CC0 %s
+// CHECK-CC0-NOT: FOO
 // RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:1 %s | FileCheck -check-prefix=CHECK-CC1 %s
 // CHECK-CC1: macro definition:{TypedText FOO}{LeftParen (}{Placeholder Arg1}{Comma , }{Placeholder Arg2}{RightParen )}
 // RUN: c-index-test -code-completion-at=%s:13:13 %s | FileCheck -check-prefix=CHECK-CC2 %s
-- 
GitLab