]> granicus.if.org Git - clang/commitdiff
After issuing a diagnostic for undefining or redefining a builtin macro,
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 6 Mar 2013 00:46:00 +0000 (00:46 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 6 Mar 2013 00:46:00 +0000 (00:46 +0000)
continue parsing the directive rather than silently discarding it.

Allowing undef or redef of __TIME__ and __DATE__ is important to folks
who want stable, reproducible builds.

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

include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticLexKinds.td
lib/Lex/PPDirectives.cpp
test/Lexer/builtin_redef.c [new file with mode: 0644]
test/Misc/warning-flags.c

index 69af40734248a7a228bc34a3359e39cc001fa539..7b921953fffb8dafa470476c1047162ec6e75b6a 100644 (file)
@@ -39,6 +39,7 @@ def NullConversion : DiagGroup<"null-conversion">;
 def ImplicitConversionFloatingPointToBool :
   DiagGroup<"implicit-conversion-floating-point-to-bool">;
 def BadArrayNewLength : DiagGroup<"bad-array-new-length">;
+def BuiltinMacroRedefined : DiagGroup<"builtin-macro-redefined">;
 def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
 def C99Compat : DiagGroup<"c99-compat">;
 def CXXCompat: DiagGroup<"c++-compat">;
index 7281d07a3bf67157b53be281027e1a7269488ce2..f693257ec9c3bfc91e067a5bf8980e3f9bc5389e 100644 (file)
@@ -253,9 +253,10 @@ def pp_pragma_sysheader_in_main_file : Warning<
 def pp_poisoning_existing_macro : Warning<"poisoning existing macro">;
 def pp_out_of_date_dependency : Warning<
   "current file is older than dependency %0">;
-def pp_undef_builtin_macro : Warning<"undefining builtin macro">;
-def pp_redef_builtin_macro : Warning<"redefining builtin macro">,
-  InGroup<DiagGroup<"builtin-macro-redefined">>;
+def ext_pp_undef_builtin_macro : ExtWarn<"undefining builtin macro">,
+  InGroup<BuiltinMacroRedefined>;
+def ext_pp_redef_builtin_macro : ExtWarn<"redefining builtin macro">,
+  InGroup<BuiltinMacroRedefined>;
 def pp_disabled_macro_expansion : Warning<
   "disabled expansion of recursive macro">, DefaultIgnore,
   InGroup<DiagGroup<"disabled-macro-expansion">>;
index 07f24c8200b691446f26f462cd5108257db6928b..8379ca8719c1b42cf0503967118622dce450d9ee 100644 (file)
@@ -143,15 +143,14 @@ void Preprocessor::ReadMacroName(Token &MacroNameTok, char isDefineUndef) {
       Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
     // Fall through on error.
   } else if (isDefineUndef && II->getPPKeywordID() == tok::pp_defined) {
-    // Error if defining "defined": C99 6.10.8.4.
+    // Error if defining "defined": C99 6.10.8/4, C++ [cpp.predefined]p4.
     Diag(MacroNameTok, diag::err_defined_macro_name);
-  } else if (isDefineUndef && II->hasMacroDefinition() &&
+  } else if (isDefineUndef == 2 && II->hasMacroDefinition() &&
              getMacroInfo(II)->isBuiltinMacro()) {
-    // Error if defining "__LINE__" and other builtins: C99 6.10.8.4.
-    if (isDefineUndef == 1)
-      Diag(MacroNameTok, diag::pp_redef_builtin_macro);
-    else
-      Diag(MacroNameTok, diag::pp_undef_builtin_macro);
+    // Warn if undefining "__LINE__" and other builtins, per C99 6.10.8/4
+    // and C++ [cpp.predefined]p4], but allow it as an extension.
+    Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
+    return;
   } else {
     // Okay, we got a good identifier node.  Return it.
     return;
@@ -1925,10 +1924,14 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) {
       if (!OtherMI->isUsed() && OtherMI->isWarnIfUnused())
         Diag(OtherMI->getDefinitionLoc(), diag::pp_macro_not_used);
 
+      // Warn if defining "__LINE__" and other builtins, per C99 6.10.8/4 and 
+      // C++ [cpp.predefined]p4, but allow it as an extension.
+      if (OtherMI->isBuiltinMacro())
+        Diag(MacroNameTok, diag::ext_pp_redef_builtin_macro);
       // Macros must be identical.  This means all tokens and whitespace
       // separation must be the same.  C99 6.10.3.2.
-      if (!OtherMI->isAllowRedefinitionsWithoutWarning() &&
-          !MI->isIdenticalTo(*OtherMI, *this)) {
+      else if (!OtherMI->isAllowRedefinitionsWithoutWarning() &&
+               !MI->isIdenticalTo(*OtherMI, *this)) {
         Diag(MI->getDefinitionLoc(), diag::ext_pp_macro_redef)
           << MacroNameTok.getIdentifierInfo();
         Diag(OtherMI->getDefinitionLoc(), diag::note_previous_definition);
diff --git a/test/Lexer/builtin_redef.c b/test/Lexer/builtin_redef.c
new file mode 100644 (file)
index 0000000..c9351dc
--- /dev/null
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 %s -D__TIME__=1234 -U__DATE__ -E 2>&1 | FileCheck %s --check-prefix=CHECK-OUT
+// RUN: %clang_cc1 %s -D__TIME__=1234 -U__DATE__ -E 2>&1 | FileCheck %s --check-prefix=CHECK-WARN
+// RUN: %clang_cc1 %s -D__TIME__=1234 -U__DATE__ -E 2>&1 -pedantic-errors | FileCheck %s --check-prefix=CHECK-ERR
+
+// CHECK-WARN: <command line>:{{.*}} warning: redefining builtin macro
+// CHECK-WARN: <command line>:{{.*}} warning: undefining builtin macro
+
+// CHECK-ERR: <command line>:{{.*}} error: redefining builtin macro
+// CHECK-ERR: <command line>:{{.*}} error: undefining builtin macro
+
+int n = __TIME__;
+__DATE__
+
+#define __FILE__ "my file"
+// CHECK-WARN: :[[@LINE-1]]:9: warning: redefining builtin macro
+// CHECK-ERR: :[[@LINE-2]]:9: error: redefining builtin macro
+
+// CHECK-OUT: int n = 1234;
+// CHECK-OUT: __DATE__
index 265e178fa768d3b654aefbe00ec331d8e7f5ac3c..931de8365b36d584d4e1e8b5f08bdc9801af50c2 100644 (file)
@@ -18,7 +18,7 @@ This test serves two purposes:
 
 The list of warnings below should NEVER grow.  It should gradually shrink to 0.
 
-CHECK: Warnings without flags (145):
+CHECK: Warnings without flags (144):
 CHECK-NEXT:   ext_delete_void_ptr_operand
 CHECK-NEXT:   ext_enum_friend
 CHECK-NEXT:   ext_expected_semi_decl_list
@@ -44,7 +44,6 @@ CHECK-NEXT:   pp_out_of_date_dependency
 CHECK-NEXT:   pp_poisoning_existing_macro
 CHECK-NEXT:   pp_pragma_once_in_main_file
 CHECK-NEXT:   pp_pragma_sysheader_in_main_file
-CHECK-NEXT:   pp_undef_builtin_macro
 CHECK-NEXT:   w_asm_qualifier_ignored
 CHECK-NEXT:   warn_accessor_property_type_mismatch
 CHECK-NEXT:   warn_anon_bitfield_width_exceeds_type_size