]> granicus.if.org Git - clang/commitdiff
Fixed a problem with #pragma push_macro/pop_macro implementation.
authorAlexander Kornienko <alexfh@google.com>
Wed, 29 Aug 2012 16:56:24 +0000 (16:56 +0000)
committerAlexander Kornienko <alexfh@google.com>
Wed, 29 Aug 2012 16:56:24 +0000 (16:56 +0000)
Summary:
The problem was with the following sequence:
  #pragma push_macro("long")
  #undef long
  #pragma pop_macro("long")
in case when "long" didn't represent a macro.
Fixed crash and removed code duplication for #undef/pop_macro case. Added regression tests.

Reviewers: doug.gregor, klimek

Reviewed By: doug.gregor

CC: cfe-commits, chapuni
Differential Revision: http://llvm-reviews.chandlerc.com/D31

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162845 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Lex/Preprocessor.h
lib/Lex/PPDirectives.cpp
lib/Lex/PPMacroExpansion.cpp
lib/Lex/Pragma.cpp
test/Preprocessor/pragma-pushpop-macro.c

index fca5796068b855e11abc941e8112de74cd04fa00..adc6b240e9619fb63b3052f5e74a0e39694683c9 100644 (file)
@@ -470,6 +470,8 @@ public:
   /// \brief Specify a macro for this identifier.
   void setMacroInfo(IdentifierInfo *II, MacroInfo *MI,
                     bool LoadedFromAST = false);
+  /// \brief Undefine a macro for this identifier.
+  void clearMacroInfo(IdentifierInfo *II);
 
   /// macro_iterator/macro_begin/macro_end - This allows you to walk the macro
   /// history table. Currently defined macros have
index 6de0e4a9f36ea1c01ae2e23a9c7febfc0a1cc86f..738bed36ba12e17cc8075f8709872afe265770be 100644 (file)
@@ -1921,10 +1921,7 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) {
     WarnUnusedMacroLocs.erase(MI->getDefinitionLoc());
 
   MI->setUndefLoc(MacroNameTok.getLocation());
-  IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
-  II->setHasMacroDefinition(false);
-  if (II->isFromAST())
-    II->setChangedSinceDeserialization();
+  clearMacroInfo(MacroNameTok.getIdentifierInfo());
 }
 
 
index 936b37009c1219791fb59b811154ba9b5a5c86c8..3f27236cac3c1ada9136e7f700c7b126215b74ae 100644 (file)
@@ -57,6 +57,15 @@ void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI,
     II->setChangedSinceDeserialization();
 }
 
+/// \brief Undefine a macro for this identifier.
+void Preprocessor::clearMacroInfo(IdentifierInfo *II) {
+  assert(II->hasMacroDefinition() && "Macro is not defined!");
+  assert(Macros[II]->getUndefLoc().isValid() && "Macro is still defined!");
+  II->setHasMacroDefinition(false);
+  if (II->isFromAST())
+    II->setChangedSinceDeserialization();
+}
+
 /// RegisterBuiltinMacro - Register the specified identifier in the identifier
 /// table and mark it as a builtin macro to be expanded.
 static IdentifierInfo *RegisterBuiltinMacro(Preprocessor &PP, const char *Name){
index acf5c74556f429005b9f202a6de7bd6c9ebf24ae..62ef8bfbcdc63ffcfd0953ef818eb225afa83365 100644 (file)
@@ -737,13 +737,18 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) {
     if (MacroInfo *CurrentMI = getMacroInfo(IdentInfo)) {
       if (CurrentMI->isWarnIfUnused())
         WarnUnusedMacroLocs.erase(CurrentMI->getDefinitionLoc());
+      CurrentMI->setUndefLoc(MessageLoc);
     }
 
     // Get the MacroInfo we want to reinstall.
     MacroInfo *MacroToReInstall = iter->second.back();
 
-    // Reinstall the previously pushed macro.
-    setMacroInfo(IdentInfo, MacroToReInstall);
+    if (MacroToReInstall) {
+      // Reinstall the previously pushed macro.
+      setMacroInfo(IdentInfo, MacroToReInstall);
+    } else if (IdentInfo->hasMacroDefinition()) {
+      clearMacroInfo(IdentInfo);
+    }
 
     // Pop PragmaPushMacroInfo stack.
     iter->second.pop_back();
index 08a65704e4cb03f59067b652d22b00fd06a4e80a..0aee074c55c774e7659b406ae44686d2d4fc1a8a 100644 (file)
@@ -31,6 +31,22 @@ int pmy1 = Y;
 #define Y 4
 int pmy2 = Y;
 
+// The sequence push, define/undef, pop caused problems if macro was not
+// previously defined.
+#pragma push_macro("PREVIOUSLY_UNDEFINED1")
+#undef PREVIOUSLY_UNDEFINED1
+#pragma pop_macro("PREVIOUSLY_UNDEFINED1")
+#ifndef PREVIOUSLY_UNDEFINED1
+int Q;
+#endif
+
+#pragma push_macro("PREVIOUSLY_UNDEFINED2")
+#define PREVIOUSLY_UNDEFINED2
+#pragma pop_macro("PREVIOUSLY_UNDEFINED2")
+#ifndef PREVIOUSLY_UNDEFINED2
+int P;
+#endif
+
 // CHECK: int pmx0 = 1
 // CHECK: int pmy0 = 2
 // CHECK: int pmx1 = 1
@@ -38,4 +54,5 @@ int pmy2 = Y;
 // CHECK: int pmx3 = 1
 // CHECK: int pmy1 = 3
 // CHECK: int pmy2 = 4
-
+// CHECK: int Q;
+// CHECK: int P;