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