From 65b3ed258f1f9892754cf9485d1a5962c71cf466 Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 30 Sep 2014 20:00:18 +0000 Subject: [PATCH] Avoid a crash after loading an #undef'd macro in code completion In code-completion, don't assume there is a MacroInfo for everything, since we aren't serializing the def corresponding to a later #undef in the same module. Also setup the HadMacro bit correctly for undefs to avoid an assertion failure. rdar://18416901 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218694 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Lex/PPMacroExpansion.cpp | 5 ++++- lib/Sema/SemaCodeComplete.cpp | 3 ++- test/Index/Inputs/module-undef.h | 2 ++ test/Index/Inputs/module.map | 2 ++ test/Index/complete-module-undef.m | 8 ++++++++ 5 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 test/Index/Inputs/module-undef.h create mode 100644 test/Index/complete-module-undef.m diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 62d2da56ba..e875860f82 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -49,7 +49,10 @@ void Preprocessor::appendMacroDirective(IdentifierInfo *II, MacroDirective *MD){ MacroDirective *&StoredMD = Macros[II]; MD->setPrevious(StoredMD); StoredMD = MD; - II->setHasMacroDefinition(MD->isDefined()); + // Setup the identifier as having associated macro history. + II->setHasMacroDefinition(true); + if (!MD->isDefined()) + II->setHasMacroDefinition(false); bool isImportedMacro = isa(MD) && cast(MD)->isImported(); if (II->isFromAST() && !isImportedMacro) diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 3d250e3bef..10b243cd50 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -2575,11 +2575,12 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, const MacroDirective *MD = PP.getMacroDirectiveHistory(Macro); assert(MD && "Not a macro?"); const MacroInfo *MI = MD->getMacroInfo(); + assert((!MD->isDefined() || MI) && "missing MacroInfo for define"); Result.AddTypedTextChunk( Result.getAllocator().CopyString(Macro->getName())); - if (!MI->isFunctionLike()) + if (!MI || !MI->isFunctionLike()) return Result.TakeString(); // Format a function-like macro with placeholders for the arguments. diff --git a/test/Index/Inputs/module-undef.h b/test/Index/Inputs/module-undef.h new file mode 100644 index 0000000000..8212d755a0 --- /dev/null +++ b/test/Index/Inputs/module-undef.h @@ -0,0 +1,2 @@ +#define MY_MACRO 1 +#undef MY_MACRO diff --git a/test/Index/Inputs/module.map b/test/Index/Inputs/module.map index 8f24840c81..4bfc109a8b 100644 --- a/test/Index/Inputs/module.map +++ b/test/Index/Inputs/module.map @@ -4,3 +4,5 @@ module ModuleNeedsVFS { export * } framework module * { } + +module ModuleUndef { header "module-undef.h" } diff --git a/test/Index/complete-module-undef.m b/test/Index/complete-module-undef.m new file mode 100644 index 0000000000..a9dd000964 --- /dev/null +++ b/test/Index/complete-module-undef.m @@ -0,0 +1,8 @@ +// RUN: rm -rf %t +// RUN: env CINDEXTEST_COMPLETION_CACHING=1 \ +// RUN: c-index-test -test-load-source-reparse 2 local %s -fmodules -fmodules-cache-path=%t -I %S/Inputs \ +// RUN: | FileCheck %s + +// rdar://18416901 (used to crash) +// CHECK: complete-module-undef.m:8:1: ModuleImport=ModuleUndef:8:1 (Definition) Extent=[8:1 - 8:20] +@import ModuleUndef; -- 2.40.0